This is a set of serverless functions triggered by Hashnode or Ghost webhooks to index posts from our publications into Algolia indicies for our search bar. They're built and configured for the DigitalOcean Functions platform and are deployed using the doctl CLI to the fCC Team's DigitalOcean account.
Here are the current Hashnode events / webhooks and their corresponding functions:
| Hashnode Event | Function |
|---|---|
| Post published | .../hashnode/add-or-update-record |
| Post deleted | .../hashnode/delete-record |
| Published post updated | .../hashnode/add-or-update-record |
And here are the current Ghost events / webhooks and their endpoints:
| Ghost Event | Function |
|---|---|
| Post published | .../ghost/add-or-update-record |
| Published post updated | .../ghost/add-or-update-record |
| Post unpublished | .../ghost/delete-record |
| Post deleted | .../ghost/delete-record |
Finally, here are the currently configured Algolia indices for each publication, which are all production unless otherwise noted:
| Publication URL | CMS | Algolia index |
|---|---|---|
| https://www.freecodecamp.org/news/ | Hashnode | news |
| http://localhost:3030 | Ghost | news-es (dev) |
| https://www.freecodecamp.org/chinese/news/ | Ghost | news-zh |
| https://www.freecodecamp.org/espanol/news/ | Ghost | news-es |
| https://www.freecodecamp.org/italian/news/ | Ghost | news-it |
| https://www.freecodecamp.org/japanese/news/ | Ghost | news-ja |
| https://www.freecodecamp.org/korean/news/ | Ghost | news-ko |
| https://www.freecodecamp.org/portuguese/news/ | Ghost | news-pt-br |
| https://www.freecodecamp.org/ukrainian/news/ | Ghost | news-uk |
- doctl installed
- An account on DigitalOcean with member-level access to the fCC Team
- Access to the Technical Accounts vault on 1Password
- An Algolia account access to the pre-configured indices above (see table)
- Clone this repo and run
npm cifrom the root directory to install the necessary packages. - Go to 1Password, search for the shared
[.env.*] [dev] [prd] Search Indexernote. - Within the
do-functions-directorycreate two new files named.env.devand.env.prd, and setALGOLIA_APP_IDandALGOLIA_ADMIN_KEYto the Algolia application ID and admin key for each respective stage using the values from the 1Password note above. - If this is your first time using doctl, create a new
fcc-devcontext withdoctl auth init --context fcc-dev(the context can be named anything, butfcc-devwill be used in the examples below). - Go to 1Password, search for the shared
[PAT] [Digital Ocean] fcc-dev-doctl-token (serverless indexer)note, copy the PAT, and paste it into the terminal when prompted. - Run
doctl auth switch --context fcc-devto switch to thefcc-devcontext.
- Functions are all within the
packages/<platform>/<function-name>directory, and each function has its own directory with anindex.jsand.includefile. The.includefile is used to include the necessary dependencies for the function. - Each function is housed within a
packages/<platform>/<function-name>directory, where<platform>is eitherhashnodeorghost, and<function-name>is the name of the function. The logic for each function is in theindex.jsfile, and the.includefile contains the dependencies that should be included in the function's__deployer__.zipfile during the build process. - The
libdirectory contains shared code that is used by all functions. This includes theutils/helpers.jsfile, which contains the Algolia client and other shared functions, the sharedpackage.jsonfor all DO functions, andnode_modulesdirectory, which is created during the build process and should be copied to each function directory using the.includefile. - New packages (groups of functions) and new individual functions should be added to the
project.ymlfile. Each package and function is mapped to directories within thepackagesdirectory. Theproject.ymlfile is used by thedoctlCLI to deploy the functions to DigitalOcean.
- For testing updates to code or new versions of npm packages, use a personal Hashnode publication and the Spanish Dockerized Ghost instance from the news repo. Use the tables above to configure the webhooks for each platform to point to the functions in the
dev-search-indexernamespace, which is pre-configured on DigitalOcean.
- To deploy changes to the
dev-search-indexernamespace, runnpm run do-deploy-devfrom the root directory. - Once you're satisfied with the changes, deploy the changes to the production namespace with
npm run do-deploy-prdfrom the root directory.
WARNING: Destroying dev or prd functions is only necessary in a few cases, such as renaming an existing function. While destroying a function should still preserve the base URL for the function, it may cause the indicies for one or more publications to get out of sync. Destroying a namespace will remove all functions within that namespace, and change the base URL, requiring all webhooks all publications to be updated.
- To remove a function, manually remove the function from the
project.ymlfile and remove the function's directory from thepackagesdirectory. Next, go to the DigitalOcean Functions dashboard, select either thedev-search-indexerorprd-search-indexernamespace, and destroy the function from the dashboard. - To remove a namespace, go to the DigitalOcean Functions dashboard and destroy either the
dev-search-indexerorprd-search-indexernamespace. This will remove all functions within the namespace and change the base URL for the functions. This should only need to be done when migrating to a new region or if the namespace is no longer needed.