AutomationFlowsAI & RAG › AppFlowy Content Sync to Vector Store

AppFlowy Content Sync to Vector Store

AppFlowy Content Sync to Vector Store. Uses n8n-nodes-appflowy, textSplitterRecursiveCharacterTextSplitter, documentDefaultDataLoader, embeddingsOllama. Event-driven trigger; 11 nodes.

Event trigger★★★★☆ complexityAI-powered11 nodesN8N Nodes AppflowyText Splitter Recursive Character Text SplitterDocument Default Data LoaderOllama EmbeddingsQdrant Vector StoreSupabase Vector Store
AI & RAG Trigger: Event Nodes: 11 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Documentdefaultdataloader → Textsplitterrecursivecharactertextsplitter recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "AppFlowy Content Sync to Vector Store",
  "nodes": [
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificDatabase",
        "databaseId": "{{ $vars.appflowy_main_database_id }}",
        "event": "rowCreated",
        "options": {}
      },
      "id": "appflowy-row-created-trigger",
      "name": "AppFlowy Row Created",
      "type": "n8n-nodes-appflowy.trigger",
      "typeVersion": 1,
      "position": [
        600,
        200
      ],
      "credentials": {
        "appFlowyApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificDatabase",
        "databaseId": "{{ $vars.appflowy_main_database_id }}",
        "event": "rowUpdated",
        "options": {}
      },
      "id": "appflowy-row-updated-trigger",
      "name": "AppFlowy Row Updated",
      "type": "n8n-nodes-appflowy.trigger",
      "typeVersion": 1,
      "position": [
        600,
        400
      ],
      "credentials": {
        "appFlowyApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "content-extraction",
              "name": "content",
              "value": "={{ $json.title ? $json.title + '\\n\\n' + ($json.content || $json.description || '') : ($json.content || $json.description || 'No content available') }}",
              "type": "string"
            },
            {
              "id": "metadata-creation",
              "name": "metadata",
              "value": "={{ { source: 'appflowy', type: 'database_row', database_id: $json.database_id, row_id: $json.id, workspace_id: $json.workspace_id, created_at: $json.created_at, updated_at: $json.updated_at, title: $json.title } }}",
              "type": "object"
            },
            {
              "id": "document-id",
              "name": "document_id",
              "value": "={{ 'appflowy_' + $json.database_id + '_' + $json.id }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "process-appflowy-content",
      "name": "Process AppFlowy Content",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        900,
        300
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "clear-existing",
              "name": "action",
              "value": "clear_existing",
              "type": "string"
            },
            {
              "id": "document-id-clear",
              "name": "document_id",
              "value": "={{ $('Process AppFlowy Content').item.json.document_id }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "prepare-vector-clear",
      "name": "Prepare Vector Clear",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1150,
        300
      ]
    },
    {
      "parameters": {
        "code": {
          "execute": {
            "code": "const { QdrantVectorStore } = require(\"@langchain/qdrant\");\nconst { OllamaEmbeddings } = require(\"@langchain/community/embeddings/ollama\");\n\nconst embeddings = new OllamaEmbeddings({\n  model: \"nomic-embed-text\",\n  baseUrl: \"http://ollama:11434\"\n});\n\nconst vectorStore = await QdrantVectorStore.fromExistingCollection(\n  embeddings,\n  {\n    url: \"http://qdrant:6333\",\n    collectionName: \"knowledge_base\",\n  }\n);\n\nconst documentIdToDelete = this.getInputData()[0].json.document_id;\n\nconst filter = {\n  must: [\n    {\n      key: \"metadata.document_id\",\n      match: {\n        value: documentIdToDelete,\n      },\n    },\n  ],\n};\n\n// Delete existing vectors for this document\nvectorStore.client.delete(\"knowledge_base\", {\n  filter\n});\n\nreturn [{ json: { document_id: documentIdToDelete, status: \"cleared\" } }];"
          }
        },
        "inputs": {
          "input": [
            {
              "type": "main",
              "required": true
            }
          ]
        },
        "outputs": {
          "output": [
            {
              "type": "main"
            }
          ]
        }
      },
      "id": "clear-existing-vectors",
      "name": "Clear Existing Vectors",
      "type": "@n8n/n8n-nodes-langchain.code",
      "typeVersion": 1,
      "position": [
        1400,
        300
      ]
    },
    {
      "parameters": {
        "chunkSize": 500,
        "chunkOverlap": 50,
        "options": {}
      },
      "id": "text-splitter",
      "name": "Recursive Character Text Splitter",
      "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
      "typeVersion": 1,
      "position": [
        1650,
        500
      ]
    },
    {
      "parameters": {
        "options": {
          "metadata": {
            "metadataValues": [
              {
                "name": "source",
                "value": "={{ $('Process AppFlowy Content').item.json.metadata.source }}"
              },
              {
                "name": "type",
                "value": "={{ $('Process AppFlowy Content').item.json.metadata.type }}"
              },
              {
                "name": "database_id",
                "value": "={{ $('Process AppFlowy Content').item.json.metadata.database_id }}"
              },
              {
                "name": "row_id",
                "value": "={{ $('Process AppFlowy Content').item.json.metadata.row_id }}"
              },
              {
                "name": "document_id",
                "value": "={{ $('Process AppFlowy Content').item.json.document_id }}"
              },
              {
                "name": "workspace_id",
                "value": "={{ $('Process AppFlowy Content').item.json.metadata.workspace_id }}"
              },
              {
                "name": "title",
                "value": "={{ $('Process AppFlowy Content').item.json.metadata.title }}"
              },
              {
                "name": "updated_at",
                "value": "={{ $('Process AppFlowy Content').item.json.metadata.updated_at }}"
              }
            ]
          }
        }
      },
      "id": "document-loader",
      "name": "Default Data Loader",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "typeVersion": 1,
      "position": [
        1650,
        300
      ]
    },
    {
      "parameters": {
        "model": "nomic-embed-text:latest"
      },
      "id": "embeddings-ollama",
      "name": "Embeddings Ollama",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOllama",
      "typeVersion": 1,
      "position": [
        1900,
        300
      ],
      "credentials": {
        "ollamaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "insert",
        "qdrantCollection": {
          "__rl": true,
          "value": "knowledge_base",
          "mode": "list",
          "cachedResultName": "knowledge_base"
        },
        "options": {}
      },
      "id": "qdrant-vector-store",
      "name": "Qdrant Vector Store Insert",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "typeVersion": 1,
      "position": [
        2150,
        300
      ],
      "credentials": {
        "qdrantApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "upsert",
        "table": {
          "__rl": true,
          "value": "knowledge_sync_log",
          "mode": "list"
        },
        "data": {
          "insert": [
            {
              "column": "document_id",
              "value": "={{ $('Process AppFlowy Content').item.json.document_id }}"
            },
            {
              "column": "source_system",
              "value": "appflowy"
            },
            {
              "column": "source_id",
              "value": "={{ $('Process AppFlowy Content').item.json.metadata.row_id }}"
            },
            {
              "column": "content_hash",
              "value": "={{ $crypto.createHash('md5').update($('Process AppFlowy Content').item.json.content).digest('hex') }}"
            },
            {
              "column": "metadata",
              "value": "={{ $('Process AppFlowy Content').item.json.metadata }}"
            },
            {
              "column": "sync_timestamp",
              "value": "={{ $now }}"
            },
            {
              "column": "status",
              "value": "synced"
            }
          ]
        },
        "options": {}
      },
      "id": "log-sync-status",
      "name": "Log Sync Status",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "typeVersion": 1,
      "position": [
        2400,
        300
      ],
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "content": "## AppFlowy Content Sync to Vector Store\n\n**Purpose:** Automatically sync AppFlowy database content to the central knowledge vector store.\n\n**Triggers:**\n- New row created in AppFlowy database\n- Existing row updated in AppFlowy database\n\n**Process:**\n1. Extract content and metadata from AppFlowy\n2. Clear existing vectors for updated content\n3. Split content into chunks\n4. Generate embeddings using Ollama\n5. Store in Qdrant vector database\n6. Log sync status to Supabase",
        "height": 400,
        "width": 600,
        "color": 4
      },
      "id": "workflow-documentation",
      "name": "Workflow Documentation",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        200,
        100
      ]
    }
  ],
  "connections": {
    "AppFlowy Row Created": {
      "main": [
        [
          {
            "node": "Process AppFlowy Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AppFlowy Row Updated": {
      "main": [
        [
          {
            "node": "Process AppFlowy Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process AppFlowy Content": {
      "main": [
        [
          {
            "node": "Prepare Vector Clear",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Vector Clear": {
      "main": [
        [
          {
            "node": "Clear Existing Vectors",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clear Existing Vectors": {
      "main": [
        [
          {
            "node": "Document Loader",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Recursive Character Text Splitter": {
      "ai_textSplitter": [
        [
          {
            "node": "Default Data Loader",
            "type": "ai_textSplitter",
            "index": 0
          }
        ]
      ]
    },
    "Default Data Loader": {
      "ai_document": [
        [
          {
            "node": "Qdrant Vector Store Insert",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Ollama": {
      "ai_embedding": [
        [
          {
            "node": "Qdrant Vector Store Insert",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Qdrant Vector Store Insert": {
      "main": [
        [
          {
            "node": "Log Sync Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "appflowy-sync-v1",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "AppFlowyContentSync",
  "tags": [
    "knowledge-management",
    "appflowy",
    "vector-store",
    "sync"
  ]
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

AppFlowy Content Sync to Vector Store. Uses n8n-nodes-appflowy, textSplitterRecursiveCharacterTextSplitter, documentDefaultDataLoader, embeddingsOllama. Event-driven trigger; 11 nodes.

Source: https://github.com/161sam/n8n-installer/blob/main/modularium/ai-workspace/AppFlowy-Content-Sync.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Indexation. Uses formTrigger, embeddingsOllama, textSplitterRecursiveCharacterTextSplitter, modelSelector. Event-driven trigger; 36 nodes.

Form Trigger, Ollama Embeddings, Text Splitter Recursive Character Text Splitter +10
AI & RAG

ejemplo RAG vs CRAG. Uses googleDrive, vectorStoreQdrant, embeddingsOllama, agent. Event-driven trigger; 30 nodes.

Google Drive, Qdrant Vector Store, Ollama Embeddings +9
AI & RAG

Local RAG AI Agent. Uses memoryPostgresChat, lmChatOllama, lmOllama, toolVectorStore. Event-driven trigger; 24 nodes.

Memory Postgres Chat, Ollama Chat, Lm Ollama +9
AI & RAG

V1 ocal RAG AI Agent. Uses memoryPostgresChat, lmChatOllama, lmOllama, toolVectorStore. Event-driven trigger; 24 nodes.

Memory Postgres Chat, Ollama Chat, Lm Ollama +9
AI & RAG

An on-premises, domain-specific AI assistant for Kaggle (tested on binary disaster-tweet classification), combining LLM, an n8n workflow engine, and Qdrant-backed Retrieval-Augmented Generation (RAG).

Local File Trigger, Document Default Data Loader, Text Splitter Recursive Character Text Splitter +10