{"id":15858049,"url":"https://github.com/bdefore/netlify-faunadb-example","last_synced_at":"2026-02-23T08:34:06.429Z","repository":{"id":51474991,"uuid":"264096224","full_name":"bdefore/netlify-faunadb-example","owner":"bdefore","description":null,"archived":false,"fork":false,"pushed_at":"2021-05-11T18:12:13.000Z","size":2905,"stargazers_count":2,"open_issues_count":9,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-27T04:03:26.365Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bdefore.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-15T04:33:37.000Z","updated_at":"2020-05-18T13:42:11.000Z","dependencies_parsed_at":"2022-09-09T05:53:38.337Z","dependency_job_id":null,"html_url":"https://github.com/bdefore/netlify-faunadb-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bdefore/netlify-faunadb-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdefore%2Fnetlify-faunadb-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdefore%2Fnetlify-faunadb-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdefore%2Fnetlify-faunadb-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdefore%2Fnetlify-faunadb-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bdefore","download_url":"https://codeload.github.com/bdefore/netlify-faunadb-example/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdefore%2Fnetlify-faunadb-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29740022,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T07:44:07.782Z","status":"ssl_error","status_checked_at":"2026-02-23T07:44:07.432Z","response_time":90,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-05T20:43:27.324Z","updated_at":"2026-02-23T08:34:06.401Z","avatar_url":"https://github.com/bdefore.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Netlify + FaunaDB \u0026nbsp;\u0026nbsp;\u0026nbsp;\u003ca href=\"https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-faunadb-example\u0026stack=fauna\"\u003e\u003cimg src=\"https://www.netlify.com/img/deploy/button.svg\"\u003e\u003c/a\u003e\n\nExample of using [FaunaDB](https://fauna.com/) with [Netlify functions](https://www.netlify.com/docs/functions/)\n\n\u003c!-- AUTO-GENERATED-CONTENT:START (TOC:collapse=true\u0026collapseText=Expand Table of Contents) --\u003e\n\u003cdetails\u003e\n\u003csummary\u003eExpand Table of Contents\u003c/summary\u003e\n\n- [About this application](#about-this-application)\n- [Setup \u0026amp; Run Locally](#setup--run-locally)\n- [TLDR; Quick Deploy](#tldr-quick-deploy)\n- [Tutorial](#tutorial)\n  * [Background](#background)\n  * [1. Create React app](#1-create-react-app)\n  * [2. Set up FaunaDB](#2-set-up-faunadb)\n  * [3. Create a function](#3-create-a-function)\n    + [Anatomy of a Lambda function](#anatomy-of-a-lambda-function)\n    + [Setting up functions for local development](#setting-up-functions-for-local-development)\n  * [4. Connect the function to the frontend app](#4-connect-the-function-to-the-frontend-app)\n  * [5. Finishing the backend Functions](#5-finishing-the-backend-functions)\n  * [Wrapping Up](#wrapping-up)\n\n\u003c/details\u003e\n\u003c!-- AUTO-GENERATED-CONTENT:END --\u003e\n\n## About this application\n\nThis application is using [React](https://reactjs.org/) for the frontend, [Netlify Functions](https://www.netlify.com/docs/functions/) for API calls, and [FaunaDB](https://fauna.com/) as the backing database.\n\n![faunadb netlify](https://user-images.githubusercontent.com/532272/42067494-5c4c2b94-7afb-11e8-91b4-0bef66d85584.png)\n\n## Deploy with one click\n\nClick the [Deploy to Netlify Button](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/fauna-one-click\u0026stack=fauna)\n\n[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-faunadb-example\u0026stack=fauna)\n\n## Setup \u0026 Run Locally\n\n1. Clone down the repository\n\n    ```bash\n    git clone https://github.com/netlify/netlify-faunadb-example.git\n    ```\n\n2. Enter the repo directory\n\n    ```bash\n    cd netlify-faunadb-example\n    ```\n\n3. Install the dependencies\n\n    ```bash\n    npm install\n    ```\n\n4. Sign up for a FaunaDB account\n\n    https://dashboard.fauna.com/accounts/register\n\n5. Create a database\n\n    In the Fauna Cloud Console:\n    - Click “New Database”\n    - Enter “Netlify” as the “Database Name”\n    - Click “Save”\n\n6. Create a database access key\n\n    In the Fauna Cloud Console:\n    - Click “Security” in the left navigation\n    - Click “New Key”\n    - Make sure that the “Database” field is set to “Netlify”\n    - Make sure that the “Role” field is set to “Admin”\n    - Enter “Netlify” as the “Key Name”\n    - Click “Save”\n\n7. Copy the database access key’s secret\n\n    Save the secret somewhere safe; you won’t get a second chance to see it.\n\n8. Set your database access secret in your terminal environment\n\n    In your terminal, run the following command:\n\n    ```bash \n    export FAUNADB_SERVER_SECRET=YourFaunaDBSecretHere\n    ```\n\n    Replace `YourFaunaDBSecretHere` with the value of the secret that you copied in the previous step.\n\n9. Bootstrap your FaunaDB collection and indexes\n\n    ```bash\n    npm run bootstrap\n    ```\n\n10. Run project locally\n\n    ```bash\n    npm start\n    ```\n\n## TLDR; Quick Deploy\n\n1. Click the [Deploy to Netlify button](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-faunadb-example)\n\n[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-faunadb-example)\n\n2. Click “Connect to GitHub”. Authorize Netlify, when asked.\n\n3. Paste your FaunaDB database access secret into the “Your FaunaDB Server Secret” field.\n\n4. Click “Save \u0026 Deploy”. Netlify clones your repo, then builds and deploys your app. All done!\n\n![setup steps](https://user-images.githubusercontent.com/532272/42069927-28e1c436-7b09-11e8-96e9-272987fc9e15.gif)\n\n## Tutorial\n\n### Background\n\nThis application is using [React](https://reactjs.org/) for the frontend, [Netlify Functions](https://www.netlify.com/docs/functions/) for API calls, and [FaunaDB](https://fauna.com/) as the backing database.\n\nWe are going to explore how to get up and running with Netlify Functions and how to deploy your own serverless backend.\n\n### 1. Create React app\n\nWe are using React for this demo app, but you can use whatever you want to manage the frontend.\n\nInto VueJS? Awesome use that.\n\nMiss the days of jQuery? Righto, jQuery away!\n\nFan of VanillaJS? By all means, have at it!\n\n1. Install create react app\n\n    ```bash\n    npm install create-react-app -g\n    ```\n2. Create the react app!\n\n    ```bash\n    create-react-app my-app\n    ```\n\n3. The react app is now setup!\n\n    ```bash\n    # change directories into my-app\n    cd my-app\n    ```\n\n### 2. Set up FaunaDB\n\nWe are using FaunaDB to hold and store all of our todo data.\n\nTo setup a FaunaDB account and get the API key we'll use to scaffold out our todos database, head over to [https://dashboard.fauna.com/accounts/register](https://dashboard.fauna.com/accounts/register) and create a free Fauna Cloud account.\n\n1. **Sign up**\n\n    ![Sign up for Fauna](https://user-images.githubusercontent.com/6691035/69237909-50e05f80-0b5c-11ea-9ddb-174058f056d9.png)\n\n2. **Create a key**\n\n    ![Create a fauna key](https://user-images.githubusercontent.com/6691035/69237938-5ccc2180-0b5c-11ea-93c1-0ac61c9da429.png)\n\n3. **Name your key and create**\n\n    ![Name the fauna key and create](https://user-images.githubusercontent.com/6691035/69237999-86854880-0b5c-11ea-8e95-6d242a6e5f51.png)\n\n4. **Copy this API key for later use, or use the [Deploy to Netlify Button](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-faunadb-example) and plugin this API key.**\n\n    ![Copy API key for future use](https://user-images.githubusercontent.com/6691035/69238071-addc1580-0b5c-11ea-80ce-8aa894875008.png)\n\n5. **Create your FaunaDB database**\n\n    Set the FaunaDB API key locally in your terminal\n\n    ```bash\n    # on mac\n    export FAUNADB_SERVER_SECRET=YourFaunaDBKeyHere\n    # on windows\n    set FAUNADB_SERVER_SECRET=YourFaunaDBKeyHere\n    ```\n\n    Replace `YourFaunaDBSecretHere` with the value of the secret that you copied in the previous step.\n\n    Add the [/scripts/bootstrap-fauna-database.js](https://github.com/netlify/netlify-faunadb-example/blob/f965df497f0de507c2dfdb1a8a32a81bbd939314/scripts/bootstrap-fauna-database.js) to the root directory of the project. This is an idempotent script that you can run one million times and have the same result (one todos database)\n\n    Next up, add the bootstrap command to npm scripts in your `package.json` file\n\n    ```json\n    {\n      \"scripts\": {\n        \"bootstrap\": \"node ./scripts/bootstrap-fauna-database.js\"\n      }\n    }\n    ```\n\n    Now we can run the `bootstrap` command to setup our Fauna database in our FaunaDB account.\n\n    ```bash\n    npm run bootstrap\n    ```\n\n    If you log in to the [FaunaDB dashboard](https://dashboard.fauna.com/) you will see your todo database.\n\n### 3. Create a function\n\nNow, let’s create a function for our app and wire that up to run locally.\n\nThe functions in our project are going to live in a `/functions` folder. You can set this to whatever you'd like but we like the `/functions` convention.\n\n#### Anatomy of a Lambda function\n\nAll AWS Lambda functions have the following signature:\n\n```js\nexports.handler = (event, context, callback) =\u003e {\n  // \"event\" has information about the path, body, headers, etc. of the request\n  console.log('event', event)\n  // \"context\" has information about the lambda environment and user details\n  console.log('context', context)\n  // The \"callback\" ends the execution of the function and returns a response back to the caller\n  return callback(null, {\n    statusCode: 200,\n    body: JSON.stringify({\n      data: '⊂◉‿◉つ'\n    })\n  })\n}\n```\n\nWe are going to use the `faunadb` npm package to connect to our Fauna Database and create an item.\n\n#### Setting up functions for local development\n\nLet's rock and roll.\n\n1. **Create a `./functions` directory**\n\n    ```bash\n    # make functions directory\n    mdkir functions\n    ```\n\n2. **Install `netlify-lambda`**\n\n    [Netlify lambda](https://github.com/netlify/netlify-lambda) is a tool for locally emulating the serverless function for development and for bundling our serverless function with third party npm modules (if we are using those)\n\n    ```\n    npm i netlify-lambda --save-dev\n    ```\n\n    To simulate our function endpoints locally, we need to setup a [proxy](https://github.com/netlify/create-react-app-lambda/blob/master/package.json#L19-L26) for webpack to use.\n\n    In `package.json` add:\n\n    ```json\n    {\n      \"name\": \"react-lambda\",\n      ...\n      \"proxy\": {\n        \"/.netlify/functions\": {\n          \"target\": \"http://localhost:9000\",\n          \"pathRewrite\": {\n            \"^/\\\\.netlify/functions\": \"\"\n          }\n        }\n      }\n    }\n    ```\n\n    This will proxy requests we make to `/.netlify/functions` to our locally-running function server at port 9000.\n\n3. **Add our `start` \u0026 `build` commands**\n\n    Let's go ahead and add our `start` \u0026 `build` command to npm scripts in `package.json`. These will let us run things locally and give a command for Netlify to build our app and functions when we are ready to deploy.\n\n    We are going to be using the `npm-run-all` npm module to run our frontend and backend in parallel in the same terminal window.\n\n    So install it!\n\n    ```\n    npm install npm-run-all --save-dev\n    ```\n\n    **About `npm start`**\n\n    The `start:app` command will run `react-scripts start` to run our react app\n\n    The `start:server` command will run `netlify-lambda serve functions -c ./webpack.config.js` to run our function code locally. The `-c webpack-config` flag lets us set a custom webpack config to [fix a module issue](https://medium.com/@danbruder/typeerror-require-is-not-a-function-webpack-faunadb-6e785858d23b) with FaunaDB module.\n\n    Running `npm start` in our terminal will run `npm-run-all --parallel start:app start:server` to fire them both up at once.\n\n    **About `npm build`**\n\n    The `build:app` command will run `react-scripts build` to run our React app.\n\n    The `build:server` command will run `netlify-lambda build functions -c ./webpack.config.js` to run our function code locally.\n\n    Running `npm run build` in our terminal will run `npm-run-all --parallel build:**` to fire them both up at once.\n\n\n    **Your `package.json` should look like**\n\n    ```json\n    {\n      \"name\": \"netlify-fauna\",\n      \"scripts\": {\n        \"👇 ABOUT-bootstrap-command\": \"💡 scaffold and setup FaunaDB #\",\n        \"bootstrap\": \"node ./scripts/bootstrap-fauna-database.js\",\n        \"👇 ABOUT-start-command\": \"💡 start the app and server #\",\n        \"start\": \"npm-run-all --parallel start:app start:server\",\n        \"start:app\": \"react-scripts start\",\n        \"start:server\": \"netlify-lambda serve functions -c ./webpack.config.js\",\n        \"👇 ABOUT-prebuild-command\": \"💡 before 'build' runs, run the 'bootstrap' command #\",\n        \"prebuild\": \"echo 'setup faunaDB' \u0026\u0026 npm run bootstrap\",\n        \"👇 ABOUT-build-command\": \"💡 build the react app and the serverless functions #\",\n        \"build\": \"npm-run-all --parallel build:**\",\n        \"build:app\": \"react-scripts build\",\n        \"build:functions\": \"netlify-lambda build functions -c ./webpack.config.js\",\n      },\n      \"dependencies\": {\n        \"faunadb\": \"^0.2.2\",\n        \"react\": \"^16.4.0\",\n        \"react-dom\": \"^16.4.0\",\n        \"react-scripts\": \"1.1.4\"\n      },\n      \"devDependencies\": {\n        \"netlify-lambda\": \"^0.4.0\",\n        \"npm-run-all\": \"^4.1.3\"\n      },\n      \"proxy\": {\n        \"/.netlify/functions\": {\n          \"target\": \"http://localhost:9000\",\n          \"pathRewrite\": {\n            \"^/\\\\.netlify/functions\": \"\"\n          }\n        }\n      }\n    }\n\n    ```\n\n4. **Install FaunaDB and write the create function**\n\n    We are going to be using the `faunadb` npm module to call into our todos index in FaunaDB.\n\n    So install it in the project.\n\n    ```bash\n    npm i faunadb --save\n    ```\n\n    Then create a new function file in `/functions` called `todos-create.js`\n\n    ```js\n    /* code from functions/todos-create.js */\n    import faunadb from 'faunadb' /* Import faunaDB sdk */\n\n    /* configure faunaDB Client with our secret */\n    const q = faunadb.query\n    const client = new faunadb.Client({\n      secret: process.env.FAUNADB_SECRET\n    })\n\n    /* export our lambda function as named \"handler\" export */\n    exports.handler = (event, context, callback) =\u003e {\n      /* parse the string body into a useable JS object */\n      const data = JSON.parse(event.body)\n      console.log(\"Function `todo-create` invoked\", data)\n      const todoItem = {\n        data: data\n      }\n      /* construct the fauna query */\n      return client.query(q.Create(q.Ref(\"classes/todos\"), todoItem))\n      .then((response) =\u003e {\n        console.log(\"success\", response)\n        /* Success! return the response with statusCode 200 */\n        return callback(null, {\n          statusCode: 200,\n          body: JSON.stringify(response)\n        })\n      }).catch((error) =\u003e {\n        console.log(\"error\", error)\n        /* Error! return the error with statusCode 400 */\n        return callback(null, {\n          statusCode: 400,\n          body: JSON.stringify(error)\n        })\n      })\n    }\n    ```\n\n### 4. Connect the function to the frontend app\n\nInside of the React app, we can now wire up the `/.netlify/functions/todos-create` endpoint to an AJAX request.\n\n```js\n// Function using fetch to POST to our API endpoint\nfunction createTodo(data) {\n  return fetch('/.netlify/functions/todos-create', {\n    body: JSON.stringify(data),\n    method: 'POST'\n  }).then(response =\u003e {\n    return response.json()\n  })\n}\n\n// Todo data\nconst myTodo = {\n  title: 'My todo title',\n  completed: false,\n}\n\n// create it!\ncreateTodo(myTodo).then((response) =\u003e {\n  console.log('API response', response)\n  // set app state\n}).catch((error) =\u003e {\n  console.log('API error', error)\n})\n```\n\nRequests to `/.netlify/function/[Function-File-Name]` will work seamlessly on localhost and on the live site because we are using the local proxy with webpack.\n\nWe will be skipping over the rest of the frontend parts of the app because you can use whatever framework you'd like to build your application.\n\nAll the demo React frontend code is [available here.](https://github.com/netlify/netlify-faunadb-example/tree/17a9ba47a8b1b2408b68e793fba4c5fd17bf85da/src)\n\n### 5. Finishing the backend Functions\n\nSo far we have created our `todo-create` function and we've seen how we make requests to our live function endpoints. It's now time to add the rest of our CRUD functions to manage our todos.\n\n1. **Read Todos by ID**\n\n    Then create a new function file in `/functions` called `todos-read.js`\n\n    ```js\n    /* code from functions/todos-read.js */\n    import faunadb from 'faunadb'\n    import getId from './utils/getId'\n\n    const q = faunadb.query\n    const client = new faunadb.Client({\n      secret: process.env.FAUNADB_SECRET\n    })\n\n    exports.handler = (event, context, callback) =\u003e {\n      const id = getId(event.path)\n      console.log(`Function 'todo-read' invoked. Read id: ${id}`)\n      return client.query(q.Get(q.Ref(`classes/todos/${id}`)))\n      .then((response) =\u003e {\n        console.log(\"success\", response)\n        return callback(null, {\n          statusCode: 200,\n          body: JSON.stringify(response)\n        })\n      }).catch((error) =\u003e {\n        console.log(\"error\", error)\n        return callback(null, {\n          statusCode: 400,\n          body: JSON.stringify(error)\n        })\n      })\n    }\n    ```\n\n2. **Read All Todos**\n\n    Then create a new function file in `/functions` called `todos-read-all.js`\n\n    ```js\n    /* code from functions/todos-read-all.js */\n    import faunadb from 'faunadb'\n\n    const q = faunadb.query\n    const client = new faunadb.Client({\n      secret: process.env.FAUNADB_SECRET\n    })\n\n    exports.handler = (event, context, callback) =\u003e {\n      console.log(\"Function `todo-read-all` invoked\")\n      return client.query(q.Paginate(q.Match(q.Ref(\"indexes/all_todos\"))))\n      .then((response) =\u003e {\n        const todoRefs = response.data\n        console.log(\"Todo refs\", todoRefs)\n        console.log(`${todoRefs.length} todos found`)\n        // create new query out of todo refs. http://bit.ly/2LG3MLg\n        const getAllTodoDataQuery = todoRefs.map((ref) =\u003e {\n          return q.Get(ref)\n        })\n        // then query the refs\n        return client.query(getAllTodoDataQuery).then((ret) =\u003e {\n          return callback(null, {\n            statusCode: 200,\n            body: JSON.stringify(ret)\n          })\n        })\n      }).catch((error) =\u003e {\n        console.log(\"error\", error)\n        return callback(null, {\n          statusCode: 400,\n          body: JSON.stringify(error)\n        })\n      })\n    }\n    ```\n\n3. **Update todo by ID**\n\n    Then create a new function file in `/functions` called `todos-update.js`\n\n    ```js\n    /* code from functions/todos-update.js */\n    import faunadb from 'faunadb'\n    import getId from './utils/getId'\n\n    const q = faunadb.query\n    const client = new faunadb.Client({\n      secret: process.env.FAUNADB_SECRET\n    })\n\n    exports.handler = (event, context, callback) =\u003e {\n      const data = JSON.parse(event.body)\n      const id = getId(event.path)\n      console.log(`Function 'todo-update' invoked. update id: ${id}`)\n      return client.query(q.Update(q.Ref(`classes/todos/${id}`), {data}))\n      .then((response) =\u003e {\n        console.log(\"success\", response)\n        return callback(null, {\n          statusCode: 200,\n          body: JSON.stringify(response)\n        })\n      }).catch((error) =\u003e {\n        console.log(\"error\", error)\n        return callback(null, {\n          statusCode: 400,\n          body: JSON.stringify(error)\n        })\n      })\n    }\n    ```\n\n\n4. **Delete by ID**\n\n    Then create a new function file in `/functions` called `todos-delete.js`\n\n    ```js\n    /* code from functions/todos-delete.js */\n    import faunadb from 'faunadb'\n    import getId from './utils/getId'\n\n    const q = faunadb.query\n    const client = new faunadb.Client({\n      secret: process.env.FAUNADB_SECRET\n    })\n\n    exports.handler = (event, context, callback) =\u003e {\n      const id = getId(event.path)\n      console.log(`Function 'todo-delete' invoked. delete id: ${id}`)\n      return client.query(q.Delete(q.Ref(`classes/todos/${id}`)))\n      .then((response) =\u003e {\n        console.log(\"success\", response)\n        return callback(null, {\n          statusCode: 200,\n          body: JSON.stringify(response)\n        })\n      }).catch((error) =\u003e {\n        console.log(\"error\", error)\n        return callback(null, {\n          statusCode: 400,\n          body: JSON.stringify(error)\n        })\n      })\n    }\n    ```\n\n\n4. **Delete batch todos**\n\n    Then create a new function file in `/functions` called `todos-delete-batch.js`\n\n    ```js\n    /* code from functions/todos-delete-batch.js */\n    import faunadb from 'faunadb'\n    import getId from './utils/getId'\n\n    const q = faunadb.query\n    const client = new faunadb.Client({\n      secret: process.env.FAUNADB_SECRET\n    })\n\n    exports.handler = (event, context, callback) =\u003e {\n      const data = JSON.parse(event.body)\n      console.log('data', data)\n      console.log(\"Function `todo-delete-batch` invoked\", data.ids)\n      // construct batch query from IDs\n      const deleteAllCompletedTodoQuery = data.ids.map((id) =\u003e {\n        return q.Delete(q.Ref(`classes/todos/${id}`))\n      })\n      // Hit fauna with the query to delete the completed items\n      return client.query(deleteAllCompletedTodoQuery)\n      .then((response) =\u003e {\n        console.log(\"success\", response)\n        return callback(null, {\n          statusCode: 200,\n          body: JSON.stringify(response)\n        })\n      }).catch((error) =\u003e {\n        console.log(\"error\", error)\n        return callback(null, {\n          statusCode: 400,\n          body: JSON.stringify(error)\n        })\n      })\n    }\n    ```\n\nAfter we deploy all these functions, we will be able to call them from our frontend code with these fetch calls:\n\n```js\n/* Frontend code from src/utils/api.js */\n/* Api methods to call /functions */\n\nconst create = (data) =\u003e {\n  return fetch('/.netlify/functions/todos-create', {\n    body: JSON.stringify(data),\n    method: 'POST'\n  }).then(response =\u003e {\n    return response.json()\n  })\n}\n\nconst readAll = () =\u003e {\n  return fetch('/.netlify/functions/todos-read-all').then((response) =\u003e {\n    return response.json()\n  })\n}\n\nconst update = (todoId, data) =\u003e {\n  return fetch(`/.netlify/functions/todos-update/${todoId}`, {\n    body: JSON.stringify(data),\n    method: 'POST'\n  }).then(response =\u003e {\n    return response.json()\n  })\n}\n\nconst deleteTodo = (todoId) =\u003e {\n  return fetch(`/.netlify/functions/todos-delete/${todoId}`, {\n    method: 'POST',\n  }).then(response =\u003e {\n    return response.json()\n  })\n}\n\nconst batchDeleteTodo = (todoIds) =\u003e {\n  return fetch(`/.netlify/functions/todos-delete-batch`, {\n    body: JSON.stringify({\n      ids: todoIds\n    }),\n    method: 'POST'\n  }).then(response =\u003e {\n    return response.json()\n  })\n}\n\nexport default {\n  create: create,\n  readAll: readAll,\n  update: update,\n  delete: deleteTodo,\n  batchDelete: batchDeleteTodo\n}\n```\n\n### Wrapping Up\n\nThat's it. You now have your own CRUD API using Netlify Functions and FaunaDB.\n\nAs you can see, functions can be extremely powerful when combined with a cloud database!\n\nThe sky is the limit on what you can build with the JAMstack and we'd love to hear about what you make. Give us a shout about it on [Twitter](https://twitter.com/netlify)\n\n**Next Steps**\n\nThis example can be improved with users/authentication. Next steps to build out the app would be:\n\n- Add in the concept of users for everyone to have their own todo list\n- Wire up authentication using the JSON web token-based [Netlify Identity](https://identity.netlify.com/)\n- Add in due dates to todos and wire up Functions to notify users via email/SMS\n- File for IPO?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbdefore%2Fnetlify-faunadb-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbdefore%2Fnetlify-faunadb-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbdefore%2Fnetlify-faunadb-example/lists"}