diff --git .gitignore .gitignore
index 769dc445e..f26f47fbd 100644
--- .gitignore
+++ .gitignore
@@ -1,6 +1,7 @@
 .DS_Store
 phpunit.xml
 .idea
+.cache
 
 lib-cov
 *.seed
diff --git .jshintignore .jshintignore
index c7593c293..a5c26e46a 100644
--- .jshintignore
+++ .jshintignore
@@ -1,3 +1,6 @@
 // 3rd party libraries
 src/bp-core/js/vendor/**/*
 src/bp-messages/js/autocomplete/*
+
+// Blocks Scripts
+src/**/js/blocks/*.js
diff --git Gruntfile.js Gruntfile.js
index 590b38872..dc0160aa2 100644
--- Gruntfile.js
+++ Gruntfile.js
@@ -17,6 +17,11 @@ module.exports = function( grunt ) {
 			'**/*.js'
 		],
 
+		BP_EXCLUDED_JS = [
+			'!js/**/*.js',
+			'!**/js/blocks/*.js'
+		],
+
 		BP_EXCLUDED_MISC = [
 		],
 
@@ -164,23 +169,6 @@ module.exports = function( grunt ) {
 				expand: true
 			}
 		},
-		makepot: {
-			target: {
-				options: {
-					cwd: BUILD_DIR,
-					domainPath: '.',
-					mainFile: 'bp-loader.php',
-					potFilename: 'buddypress.pot',
-					processPot: function( pot ) {
-						pot.headers['report-msgid-bugs-to'] = 'https://buddypress.trac.wordpress.org';
-						pot.headers['last-translator'] = 'JOHN JAMES JACOBY <jjj@buddypress.org>';
-						pot.headers['language-team'] = 'ENGLISH <jjj@buddypress.org>';
-						return pot;
-					},
-					type: 'wp-plugin'
-				}
-			}
-		},
 		imagemin: {
 			core: {
 				expand: true,
@@ -201,7 +189,7 @@ module.exports = function( grunt ) {
 						dest: BUILD_DIR,
 						dot: true,
 						expand: true,
-						src: ['**', '!**/.{svn,git}/**'].concat( BP_EXCLUDED_MISC )
+						src: ['**', '!**/.{svn,git,cache}/**', '!js/**'].concat( BP_EXCLUDED_MISC )
 					},
 					{
 						dest: BUILD_DIR,
@@ -245,7 +233,7 @@ module.exports = function( grunt ) {
 				extDot: 'last',
 				expand: true,
 				ext: '.min.js',
-				src: BP_JS
+				src: BP_JS.concat( BP_EXCLUDED_JS, BP_EXCLUDED_MISC )
 			}
 		},
 		stylelint: {
@@ -332,6 +320,20 @@ module.exports = function( grunt ) {
 				command: 'svn export --force https://github.com/buddypress/BP-REST.git/trunk bp-rest',
 				cwd: BUILD_DIR,
 				stdout: false
+			},
+			makepot: {
+				command: 'wp i18n make-pot build build/buddypress.pot --headers=\'{"Project-Id-Version": "BuddyPress", "Report-Msgid-Bugs-To": "https://buddypress.trac.wordpress.org", "Last-Translator": "JOHN JAMES JACOBY <jjj@buddypress.org>", "Language-Team": "ENGLISH <jjj@buddypress.org>"}\'',
+				stdout: true
+			},
+			blocks_build: {
+				command: 'npm run build',
+				cwd: SOURCE_DIR,
+				stdout: true
+			},
+			blocks_minify: {
+				command: 'npm run minify',
+				cwd: SOURCE_DIR,
+				stdout: true
 			}
 		},
 		jsvalidate:{
@@ -342,12 +344,12 @@ module.exports = function( grunt ) {
 			},
 			build: {
 				files: {
-					src: [BUILD_DIR + '/**/*.js']
+					src: [BUILD_DIR + '/**/*.js'].concat( BP_EXCLUDED_JS, BP_EXCLUDED_MISC )
 				}
 			},
 			src: {
 				files: {
-					src: [SOURCE_DIR + '/**/*.js'].concat( BP_EXCLUDED_MISC )
+					src: [SOURCE_DIR + '/**/*.js'].concat( BP_EXCLUDED_JS, BP_EXCLUDED_MISC )
 				}
 			}
 		},
@@ -367,9 +369,10 @@ module.exports = function( grunt ) {
 	 * Register tasks.
 	 */
 	grunt.registerTask( 'src',     ['checkDependencies', 'jsvalidate:src', 'jshint', 'stylelint', 'sass', 'postcss', 'rtlcss'] );
+	grunt.registerTask( 'makepot', ['exec:makepot'] );
 	grunt.registerTask( 'commit',  ['src', 'checktextdomain', 'imagemin', 'phplint', 'exec:phpcompat'] );
 	grunt.registerTask( 'bp_rest', [ 'exec:rest_api', 'copy:bp_rest_components', 'copy:bp_rest_core', 'clean:bp_rest' ] );
-	grunt.registerTask( 'build',   ['commit', 'clean:all', 'copy:files', 'uglify', 'jsvalidate:build', 'cssmin', 'bp_rest', 'makepot', 'exec:bpdefault', 'exec:cli'] );
+	grunt.registerTask( 'build',   ['commit', 'clean:all', 'copy:files', 'uglify:core', 'jsvalidate:build', 'exec:blocks_build', 'cssmin', 'bp_rest', 'makepot', 'exec:blocks_minify', 'exec:bpdefault', 'exec:cli'] );
 	grunt.registerTask( 'release', ['build'] );
 
 	// Testing tasks.
diff --git composer.json composer.json
index df0c4dbdd..216b1d8a6 100644
--- composer.json
+++ composer.json
@@ -31,7 +31,7 @@
 		"php": ">=5.3.0"
 	},
 	"require-dev": {
-                "phpcompatibility/phpcompatibility-wp": "*",
+		"phpcompatibility/phpcompatibility-wp": "*",
 		"dealerdirect/phpcodesniffer-composer-installer": "^0.4.3"
 	}
 }
diff --git package.json package.json
index 5e26d7be7..e54217bee 100644
--- package.json
+++ package.json
@@ -5,6 +5,8 @@
 	},
 	"description": "BuddyPress adds community features to WordPress. Member Profiles, Activity Streams, Direct Messaging, Notifications, and more!",
 	"devDependencies": {
+		"@babel/core": "~7.8.7",
+		"@wordpress/babel-preset-default": "~4.10.0",
 		"@wordpress/browserslist-config": "~2.1.4",
 		"autoprefixer": "~8.5.2",
 		"grunt": "~1.0.3",
@@ -26,8 +28,8 @@
 		"grunt-rtlcss": "~2.0.1",
 		"grunt-sass": "~2.0.0",
 		"grunt-stylelint": "~0.8.0",
-		"grunt-wp-i18n": "~1.0.2",
 		"matchdep": "~1.0.1",
+		"parcel-bundler": "~1.12.4",
 		"postcss-scss": "~1.0.6",
 		"stylelint": "~7.10.1",
 		"stylelint-config-wordpress": "~11.0.0"
@@ -35,6 +37,11 @@
 	"engines": {
 		"node": ">=6.9.1"
 	},
+	"scripts": {
+		"start": "parcel watch src/js/bp-*/*s/blocks/*.js --out-dir src --no-source-maps",
+		"build": "parcel build src/js/bp-*/*s/blocks/*.js --out-dir src --no-source-maps --no-minify",
+		"minify": "parcel build src/js/bp-*/*s/blocks/*.js --out-dir build --no-source-maps"
+	},
 	"keywords": [
 		"activity",
 		"community",
@@ -53,7 +60,6 @@
 		"url": "https://buddypress.svn.wordpress.org/trunk/"
 	},
 	"version": "6.0.0-alpha",
-	"dependencies": {},
 	"browserslist": [
 		"extends @wordpress/browserslist-config"
 	]
diff --git src/bp-core/bp-core-actions.php src/bp-core/bp-core-actions.php
index fe50c8a58..89296dd79 100644
--- src/bp-core/bp-core-actions.php
+++ src/bp-core/bp-core-actions.php
@@ -75,6 +75,7 @@ add_action( 'bp_init', 'bp_setup_globals',           4  );
 add_action( 'bp_init', 'bp_setup_canonical_stack',   5  );
 add_action( 'bp_init', 'bp_setup_nav',               6  );
 add_action( 'bp_init', 'bp_setup_title',             8  );
+add_action( 'bp_init', 'bp_blocks_init',             10 );
 add_action( 'bp_init', 'bp_core_load_admin_bar_css', 12 );
 add_action( 'bp_init', 'bp_add_rewrite_tags',        20 );
 add_action( 'bp_init', 'bp_add_rewrite_rules',       30 );
diff --git src/bp-core/bp-core-blocks.php src/bp-core/bp-core-blocks.php
new file mode 100644
index 000000000..65b4bb3b8
--- /dev/null
+++ src/bp-core/bp-core-blocks.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Core BP Blocks functions.
+ *
+ * @package BuddyPress
+ * @subpackage Core
+ * @since 6.0.0
+ */
+
+// Exit if accessed directly.
+defined( 'ABSPATH' ) || exit;
+
+/**
+ * Filters the Block Editor settings to gather BuddyPress ones into a `bp` key.
+ *
+ * @since 6.0.0
+ *
+ * @param array $editor_settings Default editor settings.
+ * @return array The editor settings including BP blocks specific ones.
+ */
+function bp_blocks_editor_settings( $editor_settings = array() ) {
+	/**
+	 * Filter here to include your BP Blocks specific settings.
+	 *
+	 * @since 6.0.0
+	 *
+	 * @param array $bp_editor_settings BP blocks specific editor settings.
+	 */
+	$bp_editor_settings = (array) apply_filters( 'bp_blocks_editor_settings', array() );
+
+	if ( $bp_editor_settings ) {
+		$editor_settings['bp'] = $bp_editor_settings;
+	}
+
+	return $editor_settings;
+}
+add_filter( 'block_editor_settings', 'bp_blocks_editor_settings' );
+
+/**
+ * Register a BuddyPress block type.
+ *
+ * @since 6.0.0
+ *
+ * @param array $args The registration arguments for the block type.
+ * @return BP_Block   The BuddyPress block type object.
+ */
+function bp_register_block( $args = array() ) {
+	return new BP_Block( $args );
+}
diff --git src/bp-core/bp-core-dependency.php src/bp-core/bp-core-dependency.php
index 6ea67ed85..cb3a3f4f5 100644
--- src/bp-core/bp-core-dependency.php
+++ src/bp-core/bp-core-dependency.php
@@ -267,6 +267,20 @@ function bp_rest_api_init() {
 	do_action( 'bp_rest_api_init' );
 }
 
+/**
+ * BP Blocks Init hook.
+ *
+ * @since 6.0.0
+ */
+function bp_blocks_init() {
+	/**
+	 * Hook here to register your BuddyPress blocks.
+	 *
+	 * @since 6.0.0
+	 */
+	do_action( 'bp_blocks_init' );
+}
+
 /**
  * Fire the 'bp_customize_register' action when the Customizer has loaded,
  * allowing scripts and styles to be initialized.
diff --git src/bp-core/classes/class-bp-block.php src/bp-core/classes/class-bp-block.php
new file mode 100644
index 000000000..722974c80
--- /dev/null
+++ src/bp-core/classes/class-bp-block.php
@@ -0,0 +1,198 @@
+<?php
+/**
+ * BP Block class.
+ *
+ * @package bp-blocks
+ * @subpackage \inc\classes\class-bp-block
+ *
+ * @since 6.0.0
+ */
+
+// Exit if accessed directly.
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+/**
+ * BP Block Class.
+ *
+ * @since 6.0.0
+ */
+class BP_Block {
+	/**
+	 * WP Block Type object.
+	 *
+	 * @since 6.0.0
+	 * @var WP_Block_Type|WP_Error
+	 */
+	public $block;
+
+	/**
+	 * The script types registered.
+	 *
+	 * @since 6.0.0
+	 * @var array
+	 */
+	private $registered_scripts;
+
+	/**
+	 * The style types registered.
+	 *
+	 * @since 6.0.0
+	 * @var array
+	 */
+	private $registered_styles;
+
+	/**
+	 * Construct the BuddyPress Block.
+	 *
+	 * @since 6.0.0
+	 *
+	 * @param array $args The registration arguments for the BP Block.
+	 */
+	public function __construct( $args ) {
+		if ( ! did_action( 'bp_blocks_init' ) ) {
+			_doing_it_wrong( __METHOD__, esc_html__( 'BP Blocks needs to be registered hooking `bp_blocks_init`', 'buddypress' ), '6.0.0' );
+		}
+
+		$min     = bp_core_get_minified_asset_suffix();
+		$wp_args = array_intersect_key(
+			$args,
+			array(
+				'name'            => '',
+				'render_callback' => '',
+				'attributes'      => '',
+				'editor_script'   => '',
+				'script'          => '',
+				'editor_style'    => '',
+				'style'           => '',
+			)
+		);
+
+		if ( ! isset( $wp_args['name'] ) || ! $wp_args['name'] || ! isset( $wp_args['editor_script'] ) || ! $wp_args['editor_script'] ) {
+			$this->block = new WP_Error( 'missing_parameters', __( 'The `name` or `editor_script` required keys are missing.', 'buddypress' ) );
+		} else {
+			// Get specific BP Blocks arguments.
+			$bp_args = array_intersect_key(
+				$args,
+				array(
+					'editor_script_url'  => '',
+					'editor_script_deps' => array(),
+					'script_url'         => '',
+					'script_deps'        => array(),
+					'editor_style_url'   => '',
+					'editor_style_deps'  => array(),
+					'style_url'          => '',
+					'style_deps'         => array(),
+				)
+			);
+
+			// Register the scripts.
+			$version                  = bp_get_version();
+			$this->registered_scripts = array();
+
+			foreach ( array( 'editor_script', 'script' ) as $script_handle_key ) {
+				if ( ! isset( $wp_args[ $script_handle_key ] ) || ! $wp_args[ $script_handle_key ] ) {
+					continue;
+				}
+
+				if ( ! isset( $bp_args[ $script_handle_key . '_url' ] ) || ! $bp_args[ $script_handle_key . '_url' ] ) {
+					continue;
+				}
+
+				$deps = array();
+				if ( isset( $bp_args[ $script_handle_key . '_deps' ] ) && is_array( $bp_args[ $script_handle_key . '_deps' ] ) ) {
+					$deps = $bp_args[ $script_handle_key . '_deps' ];
+				}
+
+				$this->registered_scripts[ $script_handle_key ] = wp_register_script(
+					$wp_args[ $script_handle_key ],
+					$bp_args[ $script_handle_key . '_url' ],
+					$deps,
+					$version,
+					true
+				);
+			}
+
+			if ( ! isset( $this->registered_scripts['editor_script'] ) || ! $this->registered_scripts['editor_script'] ) {
+				$this->block = new WP_Error( 'script_registration_error', __( 'The required `editor_script` could not be registered.', 'buddypress' ) );
+			} else {
+				// Register the styles.
+				$registered_styles = array();
+
+				foreach ( array( 'editor_style', 'style' ) as $style_handle_key ) {
+					if ( ! isset( $wp_args[ $style_handle_key ] ) || ! $wp_args[ $style_handle_key ] ) {
+						continue;
+					}
+
+					if ( ! isset( $bp_args[ $style_handle_key . '_url' ] ) || ! $bp_args[ $style_handle_key . '_url' ] ) {
+						continue;
+					}
+
+					if ( $min ) {
+						$minified_css  = str_replace( '.css', $min . '.css', $bp_args[ $style_handle_key . '_url' ] );
+						$css_file_path = str_replace( content_url(), WP_CONTENT_DIR, $minified_css );
+
+						if ( file_exists( $css_file_path ) ) {
+							$bp_args[ $style_handle_key . '_url' ] = $minified_css;
+						}
+					}
+
+					$deps = array();
+					if ( isset( $bp_args[ $style_handle_key . '_deps' ] ) && is_array( $bp_args[ $style_handle_key . '_deps' ] ) ) {
+						$deps = $bp_args[ $style_handle_key . '_deps' ];
+					}
+
+					$this->registered_styles[ $style_handle_key ] = wp_register_style(
+						$wp_args[ $style_handle_key ],
+						$bp_args[ $style_handle_key . '_url' ],
+						$deps,
+						$version
+					);
+
+					wp_style_add_data( $wp_args[ $style_handle_key ], 'rtl', 'replace' );
+					if ( $min ) {
+						wp_style_add_data( $wp_args[ $style_handle_key ], 'suffix', $min );
+					}
+				}
+
+				$name = $wp_args['name'];
+				unset( $wp_args['name'] );
+
+				// Set the Block Type.
+				$this->block = new WP_Block_Type( $name, $wp_args );
+
+				// Register the Block Type.
+				register_block_type( $this->block );
+
+				// Load Block translations if found.
+				if ( $this->block->editor_script ) {
+					/**
+					 * Filter here to use a custom directory to look for the JSON translation file into.
+					 *
+					 * @since 6.0.0
+					 *
+					 * @param string $value         Absolute path to the directory to look for the JSON translation file into.
+					 * @param string $editor_script The editor's script handle.
+					 * @param string $name          The block's name.
+					 */
+					$translation_dir = apply_filters( 'bp_block_translation_dir', null, $this->block->editor_script, $name );
+
+					/**
+					 * Filter here to use a custom domain for the JSON translation file.
+					 *
+					 * @since 6.0.0
+					 *
+					 * @param string $value         The custom domain for the JSON translation file.
+					 * @param string $editor_script The editor's script handle.
+					 * @param string $name          The block's name.
+					 */
+					$domain = apply_filters( 'bp_block_translation_dir', 'buddypress', $this->block->editor_script, $name );
+
+					// Try to load the translation.
+					$translated = wp_set_script_translations( $this->block->editor_script, $domain, $translation_dir );
+				}
+			}
+		}
+	}
+}
diff --git src/bp-core/js/blocks/bp-autocompleter.js src/bp-core/js/blocks/bp-autocompleter.js
new file mode 100644
index 000000000..89b3e9c54
--- /dev/null
+++ src/bp-core/js/blocks/bp-autocompleter.js
@@ -0,0 +1,405 @@
+// modules are defined as an array
+// [ module function, map of requires ]
+//
+// map of requires is short require name -> numeric require
+//
+// anything defined in a previous bundle is accessed via the
+// orig method which is the require for previous bundles
+parcelRequire = (function (modules, cache, entry, globalName) {
+  // Save the require from previous bundle to this closure if any
+  var previousRequire = typeof parcelRequire === 'function' && parcelRequire;
+  var nodeRequire = typeof require === 'function' && require;
+
+  function newRequire(name, jumped) {
+    if (!cache[name]) {
+      if (!modules[name]) {
+        // if we cannot find the module within our internal map or
+        // cache jump to the current global require ie. the last bundle
+        // that was added to the page.
+        var currentRequire = typeof parcelRequire === 'function' && parcelRequire;
+        if (!jumped && currentRequire) {
+          return currentRequire(name, true);
+        }
+
+        // If there are other bundles on this page the require from the
+        // previous one is saved to 'previousRequire'. Repeat this as
+        // many times as there are bundles until the module is found or
+        // we exhaust the require chain.
+        if (previousRequire) {
+          return previousRequire(name, true);
+        }
+
+        // Try the node require function if it exists.
+        if (nodeRequire && typeof name === 'string') {
+          return nodeRequire(name);
+        }
+
+        var err = new Error('Cannot find module \'' + name + '\'');
+        err.code = 'MODULE_NOT_FOUND';
+        throw err;
+      }
+
+      localRequire.resolve = resolve;
+      localRequire.cache = {};
+
+      var module = cache[name] = new newRequire.Module(name);
+
+      modules[name][0].call(module.exports, localRequire, module, module.exports, this);
+    }
+
+    return cache[name].exports;
+
+    function localRequire(x){
+      return newRequire(localRequire.resolve(x));
+    }
+
+    function resolve(x){
+      return modules[name][1][x] || x;
+    }
+  }
+
+  function Module(moduleName) {
+    this.id = moduleName;
+    this.bundle = newRequire;
+    this.exports = {};
+  }
+
+  newRequire.isParcelRequire = true;
+  newRequire.Module = Module;
+  newRequire.modules = modules;
+  newRequire.cache = cache;
+  newRequire.parent = previousRequire;
+  newRequire.register = function (id, exports) {
+    modules[id] = [function (require, module) {
+      module.exports = exports;
+    }, {}];
+  };
+
+  var error;
+  for (var i = 0; i < entry.length; i++) {
+    try {
+      newRequire(entry[i]);
+    } catch (e) {
+      // Save first error but execute all entries
+      if (!error) {
+        error = e;
+      }
+    }
+  }
+
+  if (entry.length) {
+    // Expose entry point to Node, AMD or browser globals
+    // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js
+    var mainExports = newRequire(entry[entry.length - 1]);
+
+    // CommonJS
+    if (typeof exports === "object" && typeof module !== "undefined") {
+      module.exports = mainExports;
+
+    // RequireJS
+    } else if (typeof define === "function" && define.amd) {
+     define(function () {
+       return mainExports;
+     });
+
+    // <script>
+    } else if (globalName) {
+      this[globalName] = mainExports;
+    }
+  }
+
+  // Override the current require with this new one
+  parcelRequire = newRequire;
+
+  if (error) {
+    // throw error from earlier, _after updating parcelRequire_
+    throw error;
+  }
+
+  return newRequire;
+})({"kUj2":[function(require,module,exports) {
+function _classCallCheck(instance, Constructor) {
+  if (!(instance instanceof Constructor)) {
+    throw new TypeError("Cannot call a class as a function");
+  }
+}
+
+module.exports = _classCallCheck;
+},{}],"dMjH":[function(require,module,exports) {
+function _defineProperties(target, props) {
+  for (var i = 0; i < props.length; i++) {
+    var descriptor = props[i];
+    descriptor.enumerable = descriptor.enumerable || false;
+    descriptor.configurable = true;
+    if ("value" in descriptor) descriptor.writable = true;
+    Object.defineProperty(target, descriptor.key, descriptor);
+  }
+}
+
+function _createClass(Constructor, protoProps, staticProps) {
+  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+  if (staticProps) _defineProperties(Constructor, staticProps);
+  return Constructor;
+}
+
+module.exports = _createClass;
+},{}],"FlpK":[function(require,module,exports) {
+function _typeof(obj) {
+  "@babel/helpers - typeof";
+
+  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+    module.exports = _typeof = function _typeof(obj) {
+      return typeof obj;
+    };
+  } else {
+    module.exports = _typeof = function _typeof(obj) {
+      return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+    };
+  }
+
+  return _typeof(obj);
+}
+
+module.exports = _typeof;
+},{}],"oXBW":[function(require,module,exports) {
+function _assertThisInitialized(self) {
+  if (self === void 0) {
+    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+  }
+
+  return self;
+}
+
+module.exports = _assertThisInitialized;
+},{}],"cbGp":[function(require,module,exports) {
+var _typeof = require("../helpers/typeof");
+
+var assertThisInitialized = require("./assertThisInitialized");
+
+function _possibleConstructorReturn(self, call) {
+  if (call && (_typeof(call) === "object" || typeof call === "function")) {
+    return call;
+  }
+
+  return assertThisInitialized(self);
+}
+
+module.exports = _possibleConstructorReturn;
+},{"../helpers/typeof":"FlpK","./assertThisInitialized":"oXBW"}],"XApn":[function(require,module,exports) {
+function _getPrototypeOf(o) {
+  module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
+    return o.__proto__ || Object.getPrototypeOf(o);
+  };
+  return _getPrototypeOf(o);
+}
+
+module.exports = _getPrototypeOf;
+},{}],"Omxx":[function(require,module,exports) {
+function _setPrototypeOf(o, p) {
+  module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
+    o.__proto__ = p;
+    return o;
+  };
+
+  return _setPrototypeOf(o, p);
+}
+
+module.exports = _setPrototypeOf;
+},{}],"PhTw":[function(require,module,exports) {
+var setPrototypeOf = require("./setPrototypeOf");
+
+function _inherits(subClass, superClass) {
+  if (typeof superClass !== "function" && superClass !== null) {
+    throw new TypeError("Super expression must either be null or a function");
+  }
+
+  subClass.prototype = Object.create(superClass && superClass.prototype, {
+    constructor: {
+      value: subClass,
+      writable: true,
+      configurable: true
+    }
+  });
+  if (superClass) setPrototypeOf(subClass, superClass);
+}
+
+module.exports = _inherits;
+},{"./setPrototypeOf":"Omxx"}],"xHsb":[function(require,module,exports) {
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
+
+var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
+
+var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
+
+var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
+
+var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
+
+var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * WordPress dependencies.
+ */
+var _wp$element = wp.element,
+    Component = _wp$element.Component,
+    Fragment = _wp$element.Fragment,
+    createElement = _wp$element.createElement;
+var Popover = wp.components.Popover;
+var _wp = wp,
+    apiFetch = _wp.apiFetch;
+var __ = wp.i18n.__;
+
+var BPAutocompleter = /*#__PURE__*/function (_Component) {
+  (0, _inherits2.default)(BPAutocompleter, _Component);
+
+  function BPAutocompleter() {
+    var _this;
+
+    (0, _classCallCheck2.default)(this, BPAutocompleter);
+    _this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(BPAutocompleter).apply(this, arguments));
+    _this.state = {
+      search: '',
+      items: [],
+      error: ''
+    };
+    _this.searchItemName = _this.searchItemName.bind((0, _assertThisInitialized2.default)(_this));
+    _this.selectItemName = _this.selectItemName.bind((0, _assertThisInitialized2.default)(_this));
+    return _this;
+  }
+
+  (0, _createClass2.default)(BPAutocompleter, [{
+    key: "searchItemName",
+    value: function searchItemName(value) {
+      var _this2 = this;
+
+      var search = this.state.search;
+      var _this$props = this.props,
+          component = _this$props.component,
+          objectStatus = _this$props.objectStatus;
+      this.setState({
+        search: value
+      });
+
+      if (value.length < search.length) {
+        this.setState({
+          items: []
+        });
+      }
+
+      var path = '/buddypress/v1/' + component;
+
+      if (value) {
+        path += '?search=' + encodeURIComponent(value);
+      }
+
+      if (objectStatus) {
+        path += '&status=' + objectStatus;
+      }
+
+      apiFetch({
+        path: path
+      }).then(function (items) {
+        _this2.setState({
+          items: items
+        });
+      }, function (error) {
+        _this2.setState({
+          error: error.message
+        });
+      });
+    }
+  }, {
+    key: "selectItemName",
+    value: function selectItemName(event, itemID) {
+      var onSelectItem = this.props.onSelectItem;
+      event.preventDefault();
+      this.setState({
+        search: '',
+        items: [],
+        error: ''
+      });
+      return onSelectItem({
+        itemID: itemID
+      });
+    }
+  }, {
+    key: "render",
+    value: function render() {
+      var _this3 = this;
+
+      var _this$state = this.state,
+          search = _this$state.search,
+          items = _this$state.items;
+      var _this$props2 = this.props,
+          ariaLabel = _this$props2.ariaLabel,
+          placeholder = _this$props2.placeholder,
+          useAvatar = _this$props2.useAvatar;
+      var itemsList;
+
+      if (!ariaLabel) {
+        ariaLabel = __('Item\'s name', 'buddypress');
+      }
+
+      if (!placeholder) {
+        placeholder = __('Enter Item\'s name here…', 'buddypress');
+      }
+
+      if (items.length) {
+        itemsList = items.map(function (item) {
+          return createElement("button", {
+            type: "button",
+            key: 'editor-autocompleters__item-item-' + item.id,
+            role: "option",
+            "aria-selected": "true",
+            className: "components-button components-autocomplete__result editor-autocompleters__user",
+            onClick: function onClick(event) {
+              return _this3.selectItemName(event, item.id);
+            }
+          }, useAvatar && createElement("img", {
+            key: "avatar",
+            className: "editor-autocompleters__user-avatar",
+            alt: "",
+            src: item.avatar_urls.thumb
+          }), createElement("span", {
+            key: "name",
+            className: "editor-autocompleters__user-name"
+          }, item.name), item.mention_name && createElement("span", {
+            key: "slug",
+            className: "editor-autocompleters__user-slug"
+          }, item.mention_name));
+        });
+      }
+
+      return createElement(Fragment, null, createElement("input", {
+        type: "text",
+        value: search,
+        className: "components-placeholder__input",
+        "aria-label": ariaLabel,
+        placeholder: placeholder,
+        onChange: function onChange(event) {
+          return _this3.searchItemName(event.target.value);
+        }
+      }), 0 !== items.length && createElement(Popover, {
+        className: "components-autocomplete__popover",
+        focusOnMount: false,
+        position: "bottom left"
+      }, createElement("div", {
+        className: "components-autocomplete__results"
+      }, itemsList)));
+    }
+  }]);
+  return BPAutocompleter;
+}(Component);
+
+var _default = BPAutocompleter;
+exports.default = _default;
+},{"@babel/runtime/helpers/classCallCheck":"kUj2","@babel/runtime/helpers/createClass":"dMjH","@babel/runtime/helpers/possibleConstructorReturn":"cbGp","@babel/runtime/helpers/getPrototypeOf":"XApn","@babel/runtime/helpers/assertThisInitialized":"oXBW","@babel/runtime/helpers/inherits":"PhTw"}]},{},["xHsb"], null)
\ No newline at end of file
diff --git src/bp-groups/bp-groups-blocks.php src/bp-groups/bp-groups-blocks.php
new file mode 100644
index 000000000..4f40e384e
--- /dev/null
+++ src/bp-groups/bp-groups-blocks.php
@@ -0,0 +1,254 @@
+<?php
+/**
+ * BP Groups Blocks Functions.
+ *
+ * @package   bp-blocks
+ * @subpackage \inc\bp-groups\bp-groups-blocks
+ */
+
+// Exit if accessed directly.
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+/**
+ * Register Groups Blocks.
+ *
+ * @since 6.0.0
+ */
+function bp_groups_register_blocks() {
+	bp_register_block(
+		array(
+			'name'               => 'bp/group',
+			'editor_script'      => 'bp-group-block',
+			'editor_script_url'  => plugins_url( 'js/blocks/group.js', __FILE__ ),
+			'editor_script_deps' => array(
+				'wp-blocks',
+				'wp-element',
+				'wp-components',
+				'wp-i18n',
+				'wp-api-fetch',
+				'wp-editor',
+				'wp-compose',
+				'wp-data',
+				'wp-block-editor',
+			),
+			'style'              => 'bp-group-block',
+			'style_url'          => plugins_url( 'css/blocks/group.css', __FILE__ ),
+			'render_callback'    => 'bp_groups_render_group_block',
+			'attributes'         => array(
+				'itemID'              => array(
+					'type'    => 'integer',
+					'default' => 0,
+				),
+				'avatarSize'          => array(
+					'type'    => 'string',
+					'default' => 'full',
+				),
+				'displayDescription'  => array(
+					'type'    => 'boolean',
+					'default' => true,
+				),
+				'displayActionButton' => array(
+					'type'    => 'boolean',
+					'default' => true,
+				),
+				'displayCoverImage'   => array(
+					'type'    => 'boolean',
+					'default' => true,
+				),
+			),
+		)
+	);
+}
+add_action( 'bp_blocks_init', 'bp_groups_register_blocks', 10 );
+
+/**
+ * Add BP Groups blocks specific settings to the BP Blocks Editor ones.
+ *
+ * @since 6.0.0
+ *
+ * @param array $bp_editor_settings BP blocks editor settings.
+ * @return array BP Groups blocks editor settings.
+ */
+function bp_groups_editor_settings( $bp_editor_settings = array() ) {
+	$bp = buddypress();
+
+	return array_merge(
+		$bp_editor_settings,
+		array(
+			'groups' => array(
+				'isAvatarEnabled'     => $bp->avatar && $bp->avatar->show_avatars && ! bp_disable_group_avatar_uploads(),
+				'isCoverImageEnabled' => bp_is_active( 'groups', 'cover_image' ),
+			),
+		)
+	);
+}
+add_filter( 'bp_blocks_editor_settings', 'bp_groups_editor_settings' );
+
+/**
+ * Callback function to render the BP Group Block.
+ *
+ * @since 6.0.0
+ *
+ * @param array $attributes The block attributes.
+ * @return string           HTML output.
+ */
+function bp_groups_render_group_block( $attributes = array() ) {
+	$bp = buddypress();
+
+	$block_args = wp_parse_args(
+		$attributes,
+		array(
+			'itemID'              => 0,
+			'avatarSize'          => 'full',
+			'displayDescription'  => true,
+			'displayActionButton' => true,
+			'displayCoverImage'   => true,
+		)
+	);
+
+	if ( ! $block_args['itemID'] ) {
+		return;
+	}
+
+	// Set the group ID and container classes.
+	$group_id          = (int) $block_args['itemID'];
+	$container_classes = array( 'bp-block-group' );
+
+	// Group object.
+	$group = groups_get_group( $group_id );
+
+	if ( ! $group->id ) {
+		return;
+	}
+
+	// Avatar variables.
+	$avatar           = '';
+	$avatar_container = '';
+
+	// Cover image variable.
+	$cover_image     = '';
+	$cover_style     = '';
+	$cover_container = '';
+
+	// Group name/link/description variables.
+	$group_name        = bp_get_group_name( $group );
+	$group_link        = bp_get_group_permalink( $group );
+	$group_description = '';
+	$group_content     = '';
+
+	// Group action button.
+	$action_button         = '';
+	$display_action_button = (bool) $block_args['displayActionButton'];
+
+	if ( $bp->avatar && $bp->avatar->show_avatars && ! bp_disable_group_avatar_uploads() && in_array( $block_args['avatarSize'], array( 'thumb', 'full' ), true ) ) {
+		$avatar = bp_core_fetch_avatar(
+			array(
+				'item_id' => $group->id,
+				'object'  => 'group',
+				'type'    => $block_args['avatarSize'],
+				'html'    => false,
+			)
+		);
+
+		$container_classes[] = 'avatar-' . $block_args['avatarSize'];
+	} else {
+		$container_classes[] = 'avatar-none';
+	}
+
+	if ( $avatar ) {
+		$avatar_container = sprintf(
+			'<div class="item-header-avatar">
+				<a href="%1$s">
+					<img src="%2$s" alt="%3$s" class="avatar">
+				</a>
+			</div>',
+			esc_url( $group_link ),
+			esc_url( $avatar ),
+			// Translators: %s is the group's name.
+			sprintf( esc_html__( 'Group Profile photo of %s', 'buddypress' ), $group_name )
+		);
+	}
+
+	$display_cover_image = (bool) $block_args['displayCoverImage'];
+	if ( bp_is_active( 'groups', 'cover_image' ) && $display_cover_image ) {
+		$cover_image = bp_attachments_get_attachment(
+			'url',
+			array(
+				'item_id'    => $group->id,
+				'object_dir' => 'groups',
+			)
+		);
+
+		if ( $cover_image ) {
+			$cover_style = sprintf(
+				' style="background-image: url( %s );"',
+				esc_url( $cover_image )
+			);
+		}
+
+		$cover_container = sprintf(
+			'<div class="bp-group-cover-image"%s></div>',
+			$cover_style
+		);
+
+		$container_classes[] = 'has-cover';
+	}
+
+	$display_description = (bool) $block_args['displayDescription'];
+	if ( $display_description ) {
+		$group_description = bp_get_group_description( $group );
+		$group_content     = sprintf(
+			'<div class="group-description-content">%s</div>',
+			$group_description
+		);
+
+		$container_classes[] = 'has-description';
+	}
+
+	if ( $display_action_button ) {
+		$action_button = sprintf(
+			'<div class="bp-profile-button">
+				<a href="%1$s" class="button large primary button-primary" role="button">%2$s</a>
+			</div>',
+			esc_url( $group_link ),
+			esc_html__( 'Visit Group', 'buddypress' )
+		);
+	}
+
+	$output = sprintf(
+		'<div class="%1$s">
+			%2$s
+			<div class="group-content">
+				%3$s
+				<div class="group-description">
+					<strong><a href="%4$s">%5$s</a></strong>
+					%6$s
+					%7$s
+				</div>
+			</div>
+		</div>',
+		implode( ' ', array_map( 'sanitize_html_class', $container_classes ) ),
+		$cover_container,
+		$avatar_container,
+		esc_url( $group_link ),
+		esc_html( $group_name ),
+		$group_content,
+		$action_button
+	);
+
+	// Compact all interesting parameters.
+	$params = array_merge( $block_args, compact( 'group_name', 'group_link', 'group_description', 'avatar', 'cover_image' ) );
+
+	/**
+	 * Filter here to edit the output of the single group block.
+	 *
+	 * @since 6.0.0
+	 *
+	 * @param string          $output The HTML output of the block.
+	 * @param BP_Groups_Group $group  The group object.
+	 * @param array           $params The block extended parameters.
+	 */
+	return apply_filters( 'bp_groups_render_group_block_output', $output, $group, $params );
+}
diff --git src/bp-groups/classes/class-bp-groups-component.php src/bp-groups/classes/class-bp-groups-component.php
index b53835ea0..644e1a612 100644
--- src/bp-groups/classes/class-bp-groups-component.php
+++ src/bp-groups/classes/class-bp-groups-component.php
@@ -130,6 +130,7 @@ class BP_Groups_Component extends BP_Component {
 			'functions',
 			'notifications',
 			'cssjs',
+			'blocks',
 		);
 
 		// Conditional includes.
diff --git src/bp-groups/css/blocks/group-rtl.css src/bp-groups/css/blocks/group-rtl.css
new file mode 100644
index 000000000..dce932ac8
--- /dev/null
+++ src/bp-groups/css/blocks/group-rtl.css
@@ -0,0 +1,118 @@
+/* CSS for the bp/group block */
+.bp-block-group {
+	position: relative;
+}
+
+.bp-block-group .group-content {
+	display: flex;
+}
+
+.bp-block-group.has-cover .group-content,
+.bp-block-group.has-cover .item-header-avatar,
+.bp-block-group.has-cover .group-description {
+	z-index: 2;
+}
+
+.bp-block-group .group-description {
+	width: 100%;
+}
+
+.bp-block-group.has-cover .group-description {
+	padding-top: 75px;
+}
+
+.bp-block-group.avatar-full .group-description {
+	padding-right: 35px;
+}
+
+.bp-block-group.has-cover .bp-group-cover-image {
+	background-color: #c5c5c5;
+	background-position: center top;
+	background-repeat: no-repeat;
+	background-size: cover;
+	border: 0;
+	display: block;
+	right: 0;
+	margin: 0;
+	padding: 0;
+	position: absolute;
+	top: 0;
+	width: 100%;
+	z-index: 1;
+	height: 150px;
+}
+
+.bp-block-group img.avatar {
+	width: auto;
+	height: auto;
+}
+
+.bp-block-group.avatar-none .item-header-avatar {
+	display: none;
+}
+
+.bp-block-group.avatar-none.has-cover {
+	min-height: 200px;
+}
+
+.bp-block-group.avatar-full {
+	min-height: 150px;
+}
+
+.bp-block-group.avatar-full.has-cover {
+	min-height: 300px;
+}
+
+.bp-block-group.avatar-full .item-header-avatar {
+	width: 180px;
+}
+
+.bp-block-group.has-cover.avatar-full .item-header-avatar {
+	width: 200px;
+}
+
+.bp-block-group.has-cover.avatar-full img.avatar {
+	border: solid 2px #fff;
+	background: rgba(255, 255, 255, 0.8);
+	margin-right: 20px;
+}
+
+.bp-block-group.has-cover .group-content {
+	padding-top: 75px;
+}
+
+.bp-block-group.avatar-thumb .item-header-avatar img.avatar {
+	margin-top: 15px;
+}
+
+.bp-block-group.avatar-thumb:not(.has-description) .group-content {
+	min-height: 50px;
+	align-items: center;
+}
+
+.bp-block-group .group-description-content {
+	width: 100%;
+	margin-bottom: 18px;
+}
+
+.bp-block-group.avatar-thumb .item-header-avatar {
+	width: 70px;
+}
+
+.bp-block-group.avatar-thumb.has-cover .item-header-avatar {
+	padding-top: 75px;
+}
+
+.bp-block-group .bp-profile-button {
+	width: 100%;
+	overflow: hidden;
+}
+
+.bp-block-group .bp-profile-button a.button {
+	margin: 18px 0 0;
+}
+
+.bp-block-group.has-description .bp-profile-button a.button {
+	display: block;
+	float: left;
+}
diff --git src/bp-groups/css/blocks/group.css src/bp-groups/css/blocks/group.css
new file mode 100644
index 000000000..502b70b69
--- /dev/null
+++ src/bp-groups/css/blocks/group.css
@@ -0,0 +1,118 @@
+/* CSS for the bp/group block */
+.bp-block-group {
+	position: relative;
+}
+
+.bp-block-group .group-content {
+	display: flex;
+}
+
+.bp-block-group.has-cover .group-content,
+.bp-block-group.has-cover .item-header-avatar,
+.bp-block-group.has-cover .group-description {
+	z-index: 2;
+}
+
+.bp-block-group .group-description {
+	width: 100%;
+}
+
+.bp-block-group.has-cover .group-description {
+	padding-top: 75px;
+}
+
+.bp-block-group.avatar-full .group-description {
+	padding-left: 35px;
+}
+
+.bp-block-group.has-cover .bp-group-cover-image {
+	background-color: #c5c5c5;
+	background-position: center top;
+	background-repeat: no-repeat;
+	background-size: cover;
+	border: 0;
+	display: block;
+	left: 0;
+	margin: 0;
+	padding: 0;
+	position: absolute;
+	top: 0;
+	width: 100%;
+	z-index: 1;
+	height: 150px;
+}
+
+.bp-block-group img.avatar {
+	width: auto;
+	height: auto;
+}
+
+.bp-block-group.avatar-none .item-header-avatar {
+	display: none;
+}
+
+.bp-block-group.avatar-none.has-cover {
+	min-height: 200px;
+}
+
+.bp-block-group.avatar-full {
+	min-height: 150px;
+}
+
+.bp-block-group.avatar-full.has-cover {
+	min-height: 300px;
+}
+
+.bp-block-group.avatar-full .item-header-avatar {
+	width: 180px;
+}
+
+.bp-block-group.has-cover.avatar-full .item-header-avatar {
+	width: 200px;
+}
+
+.bp-block-group.has-cover.avatar-full img.avatar {
+	border: solid 2px #fff;
+	background: rgba(255, 255, 255, 0.8);
+	margin-left: 20px;
+}
+
+.bp-block-group.has-cover .group-content {
+	padding-top: 75px;
+}
+
+.bp-block-group.avatar-thumb .item-header-avatar img.avatar {
+	margin-top: 15px;
+}
+
+.bp-block-group.avatar-thumb:not(.has-description) .group-content {
+	min-height: 50px;
+	align-items: center;
+}
+
+.bp-block-group .group-description-content {
+	width: 100%;
+	margin-bottom: 18px;
+}
+
+.bp-block-group.avatar-thumb .item-header-avatar {
+	width: 70px;
+}
+
+.bp-block-group.avatar-thumb.has-cover .item-header-avatar {
+	padding-top: 75px;
+}
+
+.bp-block-group .bp-profile-button {
+	width: 100%;
+	overflow: hidden;
+}
+
+.bp-block-group .bp-profile-button a.button {
+	margin: 18px 0 0;
+}
+
+.bp-block-group.has-description .bp-profile-button a.button {
+	display: block;
+	float: right;
+}
diff --git src/bp-groups/js/blocks/group.js src/bp-groups/js/blocks/group.js
new file mode 100644
index 000000000..6a3718555
--- /dev/null
+++ src/bp-groups/js/blocks/group.js
@@ -0,0 +1,572 @@
+// modules are defined as an array
+// [ module function, map of requires ]
+//
+// map of requires is short require name -> numeric require
+//
+// anything defined in a previous bundle is accessed via the
+// orig method which is the require for previous bundles
+parcelRequire = (function (modules, cache, entry, globalName) {
+  // Save the require from previous bundle to this closure if any
+  var previousRequire = typeof parcelRequire === 'function' && parcelRequire;
+  var nodeRequire = typeof require === 'function' && require;
+
+  function newRequire(name, jumped) {
+    if (!cache[name]) {
+      if (!modules[name]) {
+        // if we cannot find the module within our internal map or
+        // cache jump to the current global require ie. the last bundle
+        // that was added to the page.
+        var currentRequire = typeof parcelRequire === 'function' && parcelRequire;
+        if (!jumped && currentRequire) {
+          return currentRequire(name, true);
+        }
+
+        // If there are other bundles on this page the require from the
+        // previous one is saved to 'previousRequire'. Repeat this as
+        // many times as there are bundles until the module is found or
+        // we exhaust the require chain.
+        if (previousRequire) {
+          return previousRequire(name, true);
+        }
+
+        // Try the node require function if it exists.
+        if (nodeRequire && typeof name === 'string') {
+          return nodeRequire(name);
+        }
+
+        var err = new Error('Cannot find module \'' + name + '\'');
+        err.code = 'MODULE_NOT_FOUND';
+        throw err;
+      }
+
+      localRequire.resolve = resolve;
+      localRequire.cache = {};
+
+      var module = cache[name] = new newRequire.Module(name);
+
+      modules[name][0].call(module.exports, localRequire, module, module.exports, this);
+    }
+
+    return cache[name].exports;
+
+    function localRequire(x){
+      return newRequire(localRequire.resolve(x));
+    }
+
+    function resolve(x){
+      return modules[name][1][x] || x;
+    }
+  }
+
+  function Module(moduleName) {
+    this.id = moduleName;
+    this.bundle = newRequire;
+    this.exports = {};
+  }
+
+  newRequire.isParcelRequire = true;
+  newRequire.Module = Module;
+  newRequire.modules = modules;
+  newRequire.cache = cache;
+  newRequire.parent = previousRequire;
+  newRequire.register = function (id, exports) {
+    modules[id] = [function (require, module) {
+      module.exports = exports;
+    }, {}];
+  };
+
+  var error;
+  for (var i = 0; i < entry.length; i++) {
+    try {
+      newRequire(entry[i]);
+    } catch (e) {
+      // Save first error but execute all entries
+      if (!error) {
+        error = e;
+      }
+    }
+  }
+
+  if (entry.length) {
+    // Expose entry point to Node, AMD or browser globals
+    // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js
+    var mainExports = newRequire(entry[entry.length - 1]);
+
+    // CommonJS
+    if (typeof exports === "object" && typeof module !== "undefined") {
+      module.exports = mainExports;
+
+    // RequireJS
+    } else if (typeof define === "function" && define.amd) {
+     define(function () {
+       return mainExports;
+     });
+
+    // <script>
+    } else if (globalName) {
+      this[globalName] = mainExports;
+    }
+  }
+
+  // Override the current require with this new one
+  parcelRequire = newRequire;
+
+  if (error) {
+    // throw error from earlier, _after updating parcelRequire_
+    throw error;
+  }
+
+  return newRequire;
+})({"kUj2":[function(require,module,exports) {
+function _classCallCheck(instance, Constructor) {
+  if (!(instance instanceof Constructor)) {
+    throw new TypeError("Cannot call a class as a function");
+  }
+}
+
+module.exports = _classCallCheck;
+},{}],"dMjH":[function(require,module,exports) {
+function _defineProperties(target, props) {
+  for (var i = 0; i < props.length; i++) {
+    var descriptor = props[i];
+    descriptor.enumerable = descriptor.enumerable || false;
+    descriptor.configurable = true;
+    if ("value" in descriptor) descriptor.writable = true;
+    Object.defineProperty(target, descriptor.key, descriptor);
+  }
+}
+
+function _createClass(Constructor, protoProps, staticProps) {
+  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+  if (staticProps) _defineProperties(Constructor, staticProps);
+  return Constructor;
+}
+
+module.exports = _createClass;
+},{}],"FlpK":[function(require,module,exports) {
+function _typeof(obj) {
+  "@babel/helpers - typeof";
+
+  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+    module.exports = _typeof = function _typeof(obj) {
+      return typeof obj;
+    };
+  } else {
+    module.exports = _typeof = function _typeof(obj) {
+      return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+    };
+  }
+
+  return _typeof(obj);
+}
+
+module.exports = _typeof;
+},{}],"oXBW":[function(require,module,exports) {
+function _assertThisInitialized(self) {
+  if (self === void 0) {
+    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+  }
+
+  return self;
+}
+
+module.exports = _assertThisInitialized;
+},{}],"cbGp":[function(require,module,exports) {
+var _typeof = require("../helpers/typeof");
+
+var assertThisInitialized = require("./assertThisInitialized");
+
+function _possibleConstructorReturn(self, call) {
+  if (call && (_typeof(call) === "object" || typeof call === "function")) {
+    return call;
+  }
+
+  return assertThisInitialized(self);
+}
+
+module.exports = _possibleConstructorReturn;
+},{"../helpers/typeof":"FlpK","./assertThisInitialized":"oXBW"}],"XApn":[function(require,module,exports) {
+function _getPrototypeOf(o) {
+  module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
+    return o.__proto__ || Object.getPrototypeOf(o);
+  };
+  return _getPrototypeOf(o);
+}
+
+module.exports = _getPrototypeOf;
+},{}],"Omxx":[function(require,module,exports) {
+function _setPrototypeOf(o, p) {
+  module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
+    o.__proto__ = p;
+    return o;
+  };
+
+  return _setPrototypeOf(o, p);
+}
+
+module.exports = _setPrototypeOf;
+},{}],"PhTw":[function(require,module,exports) {
+var setPrototypeOf = require("./setPrototypeOf");
+
+function _inherits(subClass, superClass) {
+  if (typeof superClass !== "function" && superClass !== null) {
+    throw new TypeError("Super expression must either be null or a function");
+  }
+
+  subClass.prototype = Object.create(superClass && superClass.prototype, {
+    constructor: {
+      value: subClass,
+      writable: true,
+      configurable: true
+    }
+  });
+  if (superClass) setPrototypeOf(subClass, superClass);
+}
+
+module.exports = _inherits;
+},{"./setPrototypeOf":"Omxx"}],"xHsb":[function(require,module,exports) {
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
+
+var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
+
+var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
+
+var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
+
+var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
+
+var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * WordPress dependencies.
+ */
+var _wp$element = wp.element,
+    Component = _wp$element.Component,
+    Fragment = _wp$element.Fragment,
+    createElement = _wp$element.createElement;
+var Popover = wp.components.Popover;
+var _wp = wp,
+    apiFetch = _wp.apiFetch;
+var __ = wp.i18n.__;
+
+var BPAutocompleter = /*#__PURE__*/function (_Component) {
+  (0, _inherits2.default)(BPAutocompleter, _Component);
+
+  function BPAutocompleter() {
+    var _this;
+
+    (0, _classCallCheck2.default)(this, BPAutocompleter);
+    _this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(BPAutocompleter).apply(this, arguments));
+    _this.state = {
+      search: '',
+      items: [],
+      error: ''
+    };
+    _this.searchItemName = _this.searchItemName.bind((0, _assertThisInitialized2.default)(_this));
+    _this.selectItemName = _this.selectItemName.bind((0, _assertThisInitialized2.default)(_this));
+    return _this;
+  }
+
+  (0, _createClass2.default)(BPAutocompleter, [{
+    key: "searchItemName",
+    value: function searchItemName(value) {
+      var _this2 = this;
+
+      var search = this.state.search;
+      var _this$props = this.props,
+          component = _this$props.component,
+          objectStatus = _this$props.objectStatus;
+      this.setState({
+        search: value
+      });
+
+      if (value.length < search.length) {
+        this.setState({
+          items: []
+        });
+      }
+
+      var path = '/buddypress/v1/' + component;
+
+      if (value) {
+        path += '?search=' + encodeURIComponent(value);
+      }
+
+      if (objectStatus) {
+        path += '&status=' + objectStatus;
+      }
+
+      apiFetch({
+        path: path
+      }).then(function (items) {
+        _this2.setState({
+          items: items
+        });
+      }, function (error) {
+        _this2.setState({
+          error: error.message
+        });
+      });
+    }
+  }, {
+    key: "selectItemName",
+    value: function selectItemName(event, itemID) {
+      var onSelectItem = this.props.onSelectItem;
+      event.preventDefault();
+      this.setState({
+        search: '',
+        items: [],
+        error: ''
+      });
+      return onSelectItem({
+        itemID: itemID
+      });
+    }
+  }, {
+    key: "render",
+    value: function render() {
+      var _this3 = this;
+
+      var _this$state = this.state,
+          search = _this$state.search,
+          items = _this$state.items;
+      var _this$props2 = this.props,
+          ariaLabel = _this$props2.ariaLabel,
+          placeholder = _this$props2.placeholder,
+          useAvatar = _this$props2.useAvatar;
+      var itemsList;
+
+      if (!ariaLabel) {
+        ariaLabel = __('Item\'s name', 'buddypress');
+      }
+
+      if (!placeholder) {
+        placeholder = __('Enter Item\'s name here…', 'buddypress');
+      }
+
+      if (items.length) {
+        itemsList = items.map(function (item) {
+          return createElement("button", {
+            type: "button",
+            key: 'editor-autocompleters__item-item-' + item.id,
+            role: "option",
+            "aria-selected": "true",
+            className: "components-button components-autocomplete__result editor-autocompleters__user",
+            onClick: function onClick(event) {
+              return _this3.selectItemName(event, item.id);
+            }
+          }, useAvatar && createElement("img", {
+            key: "avatar",
+            className: "editor-autocompleters__user-avatar",
+            alt: "",
+            src: item.avatar_urls.thumb
+          }), createElement("span", {
+            key: "name",
+            className: "editor-autocompleters__user-name"
+          }, item.name), item.mention_name && createElement("span", {
+            key: "slug",
+            className: "editor-autocompleters__user-slug"
+          }, item.mention_name));
+        });
+      }
+
+      return createElement(Fragment, null, createElement("input", {
+        type: "text",
+        value: search,
+        className: "components-placeholder__input",
+        "aria-label": ariaLabel,
+        placeholder: placeholder,
+        onChange: function onChange(event) {
+          return _this3.searchItemName(event.target.value);
+        }
+      }), 0 !== items.length && createElement(Popover, {
+        className: "components-autocomplete__popover",
+        focusOnMount: false,
+        position: "bottom left"
+      }, createElement("div", {
+        className: "components-autocomplete__results"
+      }, itemsList)));
+    }
+  }]);
+  return BPAutocompleter;
+}(Component);
+
+var _default = BPAutocompleter;
+exports.default = _default;
+},{"@babel/runtime/helpers/classCallCheck":"kUj2","@babel/runtime/helpers/createClass":"dMjH","@babel/runtime/helpers/possibleConstructorReturn":"cbGp","@babel/runtime/helpers/getPrototypeOf":"XApn","@babel/runtime/helpers/assertThisInitialized":"oXBW","@babel/runtime/helpers/inherits":"PhTw"}],"pvse":[function(require,module,exports) {
+"use strict";
+
+var _bpAutocompleter = _interopRequireDefault(require("../../../bp-core/js/blocks/bp-autocompleter"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * WordPress dependencies.
+ */
+var registerBlockType = wp.blocks.registerBlockType;
+var _wp$element = wp.element,
+    createElement = _wp$element.createElement,
+    Fragment = _wp$element.Fragment;
+var _wp$components = wp.components,
+    Placeholder = _wp$components.Placeholder,
+    Disabled = _wp$components.Disabled,
+    PanelBody = _wp$components.PanelBody,
+    SelectControl = _wp$components.SelectControl,
+    ToggleControl = _wp$components.ToggleControl,
+    Toolbar = _wp$components.Toolbar,
+    ToolbarButton = _wp$components.ToolbarButton;
+var _wp$blockEditor = wp.blockEditor,
+    InspectorControls = _wp$blockEditor.InspectorControls,
+    BlockControls = _wp$blockEditor.BlockControls;
+var withSelect = wp.data.withSelect;
+var compose = wp.compose.compose;
+var ServerSideRender = wp.editor.ServerSideRender;
+var __ = wp.i18n.__;
+/**
+ * Internal dependencies.
+ */
+
+var AVATAR_SIZES = [{
+  label: __('None', 'buddypress'),
+  value: 'none'
+}, {
+  label: __('Thumb', 'buddypress'),
+  value: 'thumb'
+}, {
+  label: __('Full', 'buddypress'),
+  value: 'full'
+}];
+
+var editGroup = function editGroup(_ref) {
+  var attributes = _ref.attributes,
+      setAttributes = _ref.setAttributes,
+      bpSettings = _ref.bpSettings;
+  var isAvatarEnabled = bpSettings.isAvatarEnabled,
+      isCoverImageEnabled = bpSettings.isCoverImageEnabled;
+  var avatarSize = attributes.avatarSize,
+      displayDescription = attributes.displayDescription,
+      displayActionButton = attributes.displayActionButton,
+      displayCoverImage = attributes.displayCoverImage;
+
+  if (!attributes.itemID) {
+    return createElement(Placeholder, {
+      icon: "buddicons-groups",
+      label: __('BuddyPress Group', 'buddypress'),
+      instructions: __('Start typing the name of the group you want to feature into this post.', 'buddypress')
+    }, createElement(_bpAutocompleter.default, {
+      component: "groups",
+      objectStatus: "public",
+      ariaLabel: __('Group\'s name', 'buddypress'),
+      placeholder: __('Enter Group\'s name here…', 'buddypress'),
+      onSelectItem: setAttributes,
+      useAvatar: isAvatarEnabled
+    }));
+  }
+
+  return createElement(Fragment, null, createElement(BlockControls, null, createElement(Toolbar, null, createElement(ToolbarButton, {
+    icon: "edit",
+    title: __('Select another group', 'buddypress'),
+    onClick: function onClick() {
+      setAttributes({
+        itemID: 0
+      });
+    }
+  }))), createElement(InspectorControls, null, createElement(PanelBody, {
+    title: __('Group\'s home button settings', 'buddypress'),
+    initialOpen: true
+  }, createElement(ToggleControl, {
+    label: __('Display Group\'s home button', 'buddypress'),
+    checked: !!displayActionButton,
+    onChange: function onChange() {
+      setAttributes({
+        displayActionButton: !displayActionButton
+      });
+    },
+    help: displayActionButton ? __('Include a link to the group\'s home page under their name.', 'buddypress') : __('Toggle to display a link to the group\'s home page under their name.', 'buddypress')
+  })), createElement(PanelBody, {
+    title: __('Description settings', 'buddypress'),
+    initialOpen: false
+  }, createElement(ToggleControl, {
+    label: __('Display group\'s description', 'buddypress'),
+    checked: !!displayDescription,
+    onChange: function onChange() {
+      setAttributes({
+        displayDescription: !displayDescription
+      });
+    },
+    help: displayDescription ? __('Include the group\'s description under their name.', 'buddypress') : __('Toggle to display the group\'s description under their name.', 'buddypress')
+  })), isAvatarEnabled && createElement(PanelBody, {
+    title: __('Avatar settings', 'buddypress'),
+    initialOpen: false
+  }, createElement(SelectControl, {
+    label: __('Size', 'buddypress'),
+    value: avatarSize,
+    options: AVATAR_SIZES,
+    onChange: function onChange(option) {
+      setAttributes({
+        avatarSize: option
+      });
+    }
+  })), isCoverImageEnabled && createElement(PanelBody, {
+    title: __('Cover image settings', 'buddypress'),
+    initialOpen: false
+  }, createElement(ToggleControl, {
+    label: __('Display Cover Image', 'buddypress'),
+    checked: !!displayCoverImage,
+    onChange: function onChange() {
+      setAttributes({
+        displayCoverImage: !displayCoverImage
+      });
+    },
+    help: displayCoverImage ? __('Include the group\'s cover image over their name.', 'buddypress') : __('Toggle to display the group\'s cover image over their name.', 'buddypress')
+  }))), createElement(Disabled, null, createElement(ServerSideRender, {
+    block: "bp/group",
+    attributes: attributes
+  })));
+};
+
+var editGroupBlock = compose([withSelect(function (select) {
+  var editorSettings = select('core/editor').getEditorSettings();
+  return {
+    bpSettings: editorSettings.bp.groups || {}
+  };
+})])(editGroup);
+registerBlockType('bp/group', {
+  title: __('Group', 'buddypress'),
+  description: __('BuddyPress Group.', 'buddypress'),
+  icon: 'buddicons-groups',
+  category: 'buddypress',
+  attributes: {
+    itemID: {
+      type: 'integer',
+      default: 0
+    },
+    avatarSize: {
+      type: 'string',
+      default: 'full'
+    },
+    displayDescription: {
+      type: 'boolean',
+      default: true
+    },
+    displayActionButton: {
+      type: 'boolean',
+      default: true
+    },
+    displayCoverImage: {
+      type: 'boolean',
+      default: true
+    }
+  },
+  edit: editGroupBlock
+});
+},{"../../../bp-core/js/blocks/bp-autocompleter":"xHsb"}]},{},["pvse"], null)
\ No newline at end of file
diff --git src/bp-members/bp-members-blocks.php src/bp-members/bp-members-blocks.php
new file mode 100644
index 000000000..1c2d2fb27
--- /dev/null
+++ src/bp-members/bp-members-blocks.php
@@ -0,0 +1,245 @@
+<?php
+/**
+ * BP Members Blocks Functions.
+ *
+ * @package   bp-blocks
+ * @subpackage \inc\bp-members\bp-members-blocks
+ */
+
+// Exit if accessed directly.
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+/**
+ * Register Members Blocks.
+ *
+ * @since 6.0.0
+ */
+function bp_members_register_blocks() {
+	bp_register_block(
+		array(
+			'name'               => 'bp/member',
+			'editor_script'      => 'bp-member-block',
+			'editor_script_url'  => plugins_url( 'js/blocks/member.js', __FILE__ ),
+			'editor_script_deps' => array(
+				'wp-blocks',
+				'wp-element',
+				'wp-components',
+				'wp-i18n',
+				'wp-api-fetch',
+				'wp-editor',
+				'wp-compose',
+				'wp-data',
+				'wp-block-editor',
+			),
+			'style'              => 'bp-member-block',
+			'style_url'          => plugins_url( 'css/blocks/member.css', __FILE__ ),
+			'render_callback'    => 'bp_members_render_member_block',
+			'attributes'         => array(
+				'itemID'              => array(
+					'type'    => 'integer',
+					'default' => 0,
+				),
+				'avatarSize'          => array(
+					'type'    => 'string',
+					'default' => 'full',
+				),
+				'displayMentionSlug'  => array(
+					'type'    => 'boolean',
+					'default' => true,
+				),
+				'displayActionButton' => array(
+					'type'    => 'boolean',
+					'default' => true,
+				),
+				'displayCoverImage'   => array(
+					'type'    => 'boolean',
+					'default' => true,
+				),
+			),
+		)
+	);
+}
+add_action( 'bp_blocks_init', 'bp_members_register_blocks', 10 );
+
+/**
+ * Add BP Members blocks specific settings to the BP Blocks Editor ones.
+ *
+ * @since 6.0.0
+ *
+ * @param array $bp_editor_settings BP blocks editor settings.
+ * @return array BP Members blocks editor settings.
+ */
+function bp_members_editor_settings( $bp_editor_settings = array() ) {
+	$bp = buddypress();
+
+	return array_merge(
+		$bp_editor_settings,
+		array(
+			'members' => array(
+				'isMentionEnabled'    => bp_is_active( 'activity' ) && bp_activity_do_mentions(),
+				'isAvatarEnabled'     => $bp->avatar && $bp->avatar->show_avatars,
+				'isCoverImageEnabled' => bp_is_active( 'members', 'cover_image' ),
+			),
+		)
+	);
+}
+add_filter( 'bp_blocks_editor_settings', 'bp_members_editor_settings' );
+
+/**
+ * Callback function to render the BP Member Block.
+ *
+ * @since 6.0.0
+ *
+ * @param array $attributes The block attributes.
+ * @return string           HTML output.
+ */
+function bp_members_render_member_block( $attributes = array() ) {
+	$bp = buddypress();
+
+	$block_args = wp_parse_args(
+		$attributes,
+		array(
+			'itemID'              => 0,
+			'avatarSize'          => 'full',
+			'displayMentionSlug'  => true,
+			'displayActionButton' => true,
+			'displayCoverImage'   => true,
+		)
+	);
+
+	if ( ! $block_args['itemID'] ) {
+		return;
+	}
+
+	// Set the member ID and container classes.
+	$member_id         = (int) $block_args['itemID'];
+	$container_classes = array( 'bp-block-member' );
+
+	// Mention variables.
+	$username   = bp_core_get_username( $member_id );
+	$at_mention = '';
+
+	// Avatar variables.
+	$avatar           = '';
+	$avatar_container = '';
+
+	// Cover image variable.
+	$cover_image     = '';
+	$cover_style     = '';
+	$cover_container = '';
+
+	// Member name variables.
+	$display_name = bp_core_get_user_displayname( $member_id );
+	$member_link  = bp_core_get_user_domain( $member_id );
+
+	// Member action button.
+	$action_button         = '';
+	$display_action_button = (bool) $block_args['displayActionButton'];
+
+	if ( $bp->avatar && $bp->avatar->show_avatars && in_array( $block_args['avatarSize'], array( 'thumb', 'full' ), true ) ) {
+		$avatar = bp_core_fetch_avatar(
+			array(
+				'item_id' => $member_id,
+				'object'  => 'user',
+				'type'    => $block_args['avatarSize'],
+				'html'    => false,
+			)
+		);
+
+		$container_classes[] = 'avatar-' . $block_args['avatarSize'];
+	} else {
+		$container_classes[] = 'avatar-none';
+	}
+
+	if ( $avatar ) {
+		$avatar_container = sprintf(
+			'<div class="item-header-avatar">
+				<a href="%1$s">
+					<img src="%2$s" alt="%3$s" class="avatar">
+				</a>
+			</div>',
+			esc_url( $member_link ),
+			esc_url( $avatar ),
+			// Translators: %s is the member's display name.
+			sprintf( esc_html__( 'Profile photo of %s', 'buddypress' ), $display_name )
+		);
+	}
+
+	$display_cover_image = (bool) $block_args['displayCoverImage'];
+	if ( bp_is_active( 'members', 'cover_image' ) && $display_cover_image ) {
+		$cover_image = bp_attachments_get_attachment(
+			'url',
+			array(
+				'item_id' => $member_id,
+			)
+		);
+
+		if ( $cover_image ) {
+			$cover_style = sprintf(
+				' style="background-image: url( %s );"',
+				esc_url( $cover_image )
+			);
+		}
+
+		$cover_container = sprintf(
+			'<div class="bp-member-cover-image"%s></div>',
+			$cover_style
+		);
+
+		$container_classes[] = 'has-cover';
+	}
+
+	$display_mention_slug = (bool) $block_args['displayMentionSlug'];
+	if ( bp_is_active( 'activity' ) && bp_activity_do_mentions() && $display_mention_slug ) {
+		$at_mention = sprintf(
+			'<span class="user-nicename">@%s</span>',
+			esc_html( $username )
+		);
+	}
+
+	if ( $display_action_button ) {
+		$action_button = sprintf(
+			'<div class="bp-profile-button">
+				<a href="%1$s" class="button large primary button-primary" role="button">%2$s</a>
+			</div>',
+			esc_url( $member_link ),
+			esc_html__( 'View Profile', 'buddypress' )
+		);
+	}
+
+	$output = sprintf(
+		'<div class="%1$s">
+			%2$s
+			<div class="member-content">
+				%3$s
+				<div class="member-description">
+					<strong><a href="%4$s">%5$s</a></strong>
+					%6$s
+					%7$s
+				</div>
+			</div>
+		</div>',
+		implode( ' ', array_map( 'sanitize_html_class', $container_classes ) ),
+		$cover_container,
+		$avatar_container,
+		esc_url( $member_link ),
+		esc_html( $display_name ),
+		$at_mention,
+		$action_button
+	);
+
+	// Compact all interesting parameters.
+	$params = array_merge( $block_args, compact( 'username', 'display_name', 'member_link', 'avatar', 'cover_image' ) );
+
+	/**
+	 * Filter here to edit the output of the single member block.
+	 *
+	 * @since 6.0.0
+	 *
+	 * @param string          $output The HTML output of the block.
+	 * @param array           $params The block extended parameters.
+	 */
+	return apply_filters( 'bp_members_render_member_block_output', $output, $params );
+}
diff --git src/bp-members/classes/class-bp-members-component.php src/bp-members/classes/class-bp-members-component.php
index 29576b52f..af46a4689 100644
--- src/bp-members/classes/class-bp-members-component.php
+++ src/bp-members/classes/class-bp-members-component.php
@@ -61,6 +61,7 @@ class BP_Members_Component extends BP_Component {
 			'template',
 			'adminbar',
 			'functions',
+			'blocks',
 			'widgets',
 			'cache',
 		);
diff --git src/bp-members/css/blocks/member-rtl.css src/bp-members/css/blocks/member-rtl.css
new file mode 100644
index 000000000..ff9de024c
--- /dev/null
+++ src/bp-members/css/blocks/member-rtl.css
@@ -0,0 +1,110 @@
+/* CSS for the bp/member block */
+.bp-block-member {
+	position: relative;
+}
+
+.bp-block-member .member-content {
+	display: flex;
+}
+
+.bp-block-member.has-cover .member-content,
+.bp-block-member.has-cover .item-header-avatar,
+.bp-block-member.has-cover .member-description {
+	z-index: 2;
+}
+
+.bp-block-member.has-cover .member-description {
+	padding-top: 75px;
+}
+
+.bp-block-member.has-cover .bp-member-cover-image {
+	background-color: #c5c5c5;
+	background-position: center top;
+	background-repeat: no-repeat;
+	background-size: cover;
+	border: 0;
+	display: block;
+	right: 0;
+	margin: 0;
+	padding: 0;
+	position: absolute;
+	top: 0;
+	width: 100%;
+	z-index: 1;
+	height: 150px;
+}
+
+.bp-block-member img.avatar {
+	width: auto;
+	height: auto;
+}
+
+.bp-block-member.avatar-none .item-header-avatar {
+	display: none;
+}
+
+.bp-block-member.avatar-none.has-cover {
+	min-height: 200px;
+}
+
+.bp-block-member.avatar-full {
+	min-height: 150px;
+}
+
+.bp-block-member.avatar-full.has-cover {
+	min-height: 300px;
+}
+
+.bp-block-member.avatar-full .item-header-avatar {
+	width: 180px;
+}
+
+.bp-block-member.has-cover.avatar-full .item-header-avatar {
+	width: 200px;
+}
+
+.bp-block-member.has-cover.avatar-full img.avatar {
+	border: solid 2px #fff;
+	background: rgba(255, 255, 255, 0.8);
+	margin-right: 20px;
+}
+
+.bp-block-member.has-cover .member-content {
+	padding-top: 75px;
+}
+
+.bp-block-member.avatar-thumb .member-content {
+	min-height: 50px;
+	align-items: center;
+}
+
+.bp-block-member.avatar-thumb .item-header-avatar {
+	width: 70px;
+}
+
+.bp-block-member.avatar-thumb.has-cover .item-header-avatar {
+	padding-top: 75px;
+}
+
+.bp-block-member .user-nicename {
+	display: block;
+}
+
+.bp-block-member .user-nicename a,
+.entry .entry-content .bp-block-member .user-nicename a {
+	color: currentColor;
+	text-decoration: none;
+	border: none;
+}
+
+.bp-block-member .bp-profile-button {
+	width: 100%;
+}
+
+.bp-block-member .bp-profile-button a.button {
+	position: absolute;
+	bottom: 10px;
+	left: 0;
+	display: inline-block;
+	margin: 18px 0 0;
+}
diff --git src/bp-members/css/blocks/member.css src/bp-members/css/blocks/member.css
new file mode 100644
index 000000000..b03ea8687
--- /dev/null
+++ src/bp-members/css/blocks/member.css
@@ -0,0 +1,110 @@
+/* CSS for the bp/member block */
+.bp-block-member {
+	position: relative;
+}
+
+.bp-block-member .member-content {
+	display: flex;
+}
+
+.bp-block-member.has-cover .member-content,
+.bp-block-member.has-cover .item-header-avatar,
+.bp-block-member.has-cover .member-description {
+	z-index: 2;
+}
+
+.bp-block-member.has-cover .member-description {
+	padding-top: 75px;
+}
+
+.bp-block-member.has-cover .bp-member-cover-image {
+	background-color: #c5c5c5;
+	background-position: center top;
+	background-repeat: no-repeat;
+	background-size: cover;
+	border: 0;
+	display: block;
+	left: 0;
+	margin: 0;
+	padding: 0;
+	position: absolute;
+	top: 0;
+	width: 100%;
+	z-index: 1;
+	height: 150px;
+}
+
+.bp-block-member img.avatar {
+	width: auto;
+	height: auto;
+}
+
+.bp-block-member.avatar-none .item-header-avatar {
+	display: none;
+}
+
+.bp-block-member.avatar-none.has-cover {
+	min-height: 200px;
+}
+
+.bp-block-member.avatar-full {
+	min-height: 150px;
+}
+
+.bp-block-member.avatar-full.has-cover {
+	min-height: 300px;
+}
+
+.bp-block-member.avatar-full .item-header-avatar {
+	width: 180px;
+}
+
+.bp-block-member.has-cover.avatar-full .item-header-avatar {
+	width: 200px;
+}
+
+.bp-block-member.has-cover.avatar-full img.avatar {
+	border: solid 2px #fff;
+	background: rgba(255, 255, 255, 0.8);
+	margin-left: 20px;
+}
+
+.bp-block-member.has-cover .member-content {
+	padding-top: 75px;
+}
+
+.bp-block-member.avatar-thumb .member-content {
+	min-height: 50px;
+	align-items: center;
+}
+
+.bp-block-member.avatar-thumb .item-header-avatar {
+	width: 70px;
+}
+
+.bp-block-member.avatar-thumb.has-cover .item-header-avatar {
+	padding-top: 75px;
+}
+
+.bp-block-member .user-nicename {
+	display: block;
+}
+
+.bp-block-member .user-nicename a,
+.entry .entry-content .bp-block-member .user-nicename a {
+	color: currentColor;
+	text-decoration: none;
+	border: none;
+}
+
+.bp-block-member .bp-profile-button {
+	width: 100%;
+}
+
+.bp-block-member .bp-profile-button a.button {
+	position: absolute;
+	bottom: 10px;
+	right: 0;
+	display: inline-block;
+	margin: 18px 0 0;
+}
diff --git src/bp-members/js/blocks/member.js src/bp-members/js/blocks/member.js
new file mode 100644
index 000000000..2bbb30326
--- /dev/null
+++ src/bp-members/js/blocks/member.js
@@ -0,0 +1,572 @@
+// modules are defined as an array
+// [ module function, map of requires ]
+//
+// map of requires is short require name -> numeric require
+//
+// anything defined in a previous bundle is accessed via the
+// orig method which is the require for previous bundles
+parcelRequire = (function (modules, cache, entry, globalName) {
+  // Save the require from previous bundle to this closure if any
+  var previousRequire = typeof parcelRequire === 'function' && parcelRequire;
+  var nodeRequire = typeof require === 'function' && require;
+
+  function newRequire(name, jumped) {
+    if (!cache[name]) {
+      if (!modules[name]) {
+        // if we cannot find the module within our internal map or
+        // cache jump to the current global require ie. the last bundle
+        // that was added to the page.
+        var currentRequire = typeof parcelRequire === 'function' && parcelRequire;
+        if (!jumped && currentRequire) {
+          return currentRequire(name, true);
+        }
+
+        // If there are other bundles on this page the require from the
+        // previous one is saved to 'previousRequire'. Repeat this as
+        // many times as there are bundles until the module is found or
+        // we exhaust the require chain.
+        if (previousRequire) {
+          return previousRequire(name, true);
+        }
+
+        // Try the node require function if it exists.
+        if (nodeRequire && typeof name === 'string') {
+          return nodeRequire(name);
+        }
+
+        var err = new Error('Cannot find module \'' + name + '\'');
+        err.code = 'MODULE_NOT_FOUND';
+        throw err;
+      }
+
+      localRequire.resolve = resolve;
+      localRequire.cache = {};
+
+      var module = cache[name] = new newRequire.Module(name);
+
+      modules[name][0].call(module.exports, localRequire, module, module.exports, this);
+    }
+
+    return cache[name].exports;
+
+    function localRequire(x){
+      return newRequire(localRequire.resolve(x));
+    }
+
+    function resolve(x){
+      return modules[name][1][x] || x;
+    }
+  }
+
+  function Module(moduleName) {
+    this.id = moduleName;
+    this.bundle = newRequire;
+    this.exports = {};
+  }
+
+  newRequire.isParcelRequire = true;
+  newRequire.Module = Module;
+  newRequire.modules = modules;
+  newRequire.cache = cache;
+  newRequire.parent = previousRequire;
+  newRequire.register = function (id, exports) {
+    modules[id] = [function (require, module) {
+      module.exports = exports;
+    }, {}];
+  };
+
+  var error;
+  for (var i = 0; i < entry.length; i++) {
+    try {
+      newRequire(entry[i]);
+    } catch (e) {
+      // Save first error but execute all entries
+      if (!error) {
+        error = e;
+      }
+    }
+  }
+
+  if (entry.length) {
+    // Expose entry point to Node, AMD or browser globals
+    // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js
+    var mainExports = newRequire(entry[entry.length - 1]);
+
+    // CommonJS
+    if (typeof exports === "object" && typeof module !== "undefined") {
+      module.exports = mainExports;
+
+    // RequireJS
+    } else if (typeof define === "function" && define.amd) {
+     define(function () {
+       return mainExports;
+     });
+
+    // <script>
+    } else if (globalName) {
+      this[globalName] = mainExports;
+    }
+  }
+
+  // Override the current require with this new one
+  parcelRequire = newRequire;
+
+  if (error) {
+    // throw error from earlier, _after updating parcelRequire_
+    throw error;
+  }
+
+  return newRequire;
+})({"kUj2":[function(require,module,exports) {
+function _classCallCheck(instance, Constructor) {
+  if (!(instance instanceof Constructor)) {
+    throw new TypeError("Cannot call a class as a function");
+  }
+}
+
+module.exports = _classCallCheck;
+},{}],"dMjH":[function(require,module,exports) {
+function _defineProperties(target, props) {
+  for (var i = 0; i < props.length; i++) {
+    var descriptor = props[i];
+    descriptor.enumerable = descriptor.enumerable || false;
+    descriptor.configurable = true;
+    if ("value" in descriptor) descriptor.writable = true;
+    Object.defineProperty(target, descriptor.key, descriptor);
+  }
+}
+
+function _createClass(Constructor, protoProps, staticProps) {
+  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+  if (staticProps) _defineProperties(Constructor, staticProps);
+  return Constructor;
+}
+
+module.exports = _createClass;
+},{}],"FlpK":[function(require,module,exports) {
+function _typeof(obj) {
+  "@babel/helpers - typeof";
+
+  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+    module.exports = _typeof = function _typeof(obj) {
+      return typeof obj;
+    };
+  } else {
+    module.exports = _typeof = function _typeof(obj) {
+      return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+    };
+  }
+
+  return _typeof(obj);
+}
+
+module.exports = _typeof;
+},{}],"oXBW":[function(require,module,exports) {
+function _assertThisInitialized(self) {
+  if (self === void 0) {
+    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+  }
+
+  return self;
+}
+
+module.exports = _assertThisInitialized;
+},{}],"cbGp":[function(require,module,exports) {
+var _typeof = require("../helpers/typeof");
+
+var assertThisInitialized = require("./assertThisInitialized");
+
+function _possibleConstructorReturn(self, call) {
+  if (call && (_typeof(call) === "object" || typeof call === "function")) {
+    return call;
+  }
+
+  return assertThisInitialized(self);
+}
+
+module.exports = _possibleConstructorReturn;
+},{"../helpers/typeof":"FlpK","./assertThisInitialized":"oXBW"}],"XApn":[function(require,module,exports) {
+function _getPrototypeOf(o) {
+  module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
+    return o.__proto__ || Object.getPrototypeOf(o);
+  };
+  return _getPrototypeOf(o);
+}
+
+module.exports = _getPrototypeOf;
+},{}],"Omxx":[function(require,module,exports) {
+function _setPrototypeOf(o, p) {
+  module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
+    o.__proto__ = p;
+    return o;
+  };
+
+  return _setPrototypeOf(o, p);
+}
+
+module.exports = _setPrototypeOf;
+},{}],"PhTw":[function(require,module,exports) {
+var setPrototypeOf = require("./setPrototypeOf");
+
+function _inherits(subClass, superClass) {
+  if (typeof superClass !== "function" && superClass !== null) {
+    throw new TypeError("Super expression must either be null or a function");
+  }
+
+  subClass.prototype = Object.create(superClass && superClass.prototype, {
+    constructor: {
+      value: subClass,
+      writable: true,
+      configurable: true
+    }
+  });
+  if (superClass) setPrototypeOf(subClass, superClass);
+}
+
+module.exports = _inherits;
+},{"./setPrototypeOf":"Omxx"}],"xHsb":[function(require,module,exports) {
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
+
+var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
+
+var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
+
+var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
+
+var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
+
+var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * WordPress dependencies.
+ */
+var _wp$element = wp.element,
+    Component = _wp$element.Component,
+    Fragment = _wp$element.Fragment,
+    createElement = _wp$element.createElement;
+var Popover = wp.components.Popover;
+var _wp = wp,
+    apiFetch = _wp.apiFetch;
+var __ = wp.i18n.__;
+
+var BPAutocompleter = /*#__PURE__*/function (_Component) {
+  (0, _inherits2.default)(BPAutocompleter, _Component);
+
+  function BPAutocompleter() {
+    var _this;
+
+    (0, _classCallCheck2.default)(this, BPAutocompleter);
+    _this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(BPAutocompleter).apply(this, arguments));
+    _this.state = {
+      search: '',
+      items: [],
+      error: ''
+    };
+    _this.searchItemName = _this.searchItemName.bind((0, _assertThisInitialized2.default)(_this));
+    _this.selectItemName = _this.selectItemName.bind((0, _assertThisInitialized2.default)(_this));
+    return _this;
+  }
+
+  (0, _createClass2.default)(BPAutocompleter, [{
+    key: "searchItemName",
+    value: function searchItemName(value) {
+      var _this2 = this;
+
+      var search = this.state.search;
+      var _this$props = this.props,
+          component = _this$props.component,
+          objectStatus = _this$props.objectStatus;
+      this.setState({
+        search: value
+      });
+
+      if (value.length < search.length) {
+        this.setState({
+          items: []
+        });
+      }
+
+      var path = '/buddypress/v1/' + component;
+
+      if (value) {
+        path += '?search=' + encodeURIComponent(value);
+      }
+
+      if (objectStatus) {
+        path += '&status=' + objectStatus;
+      }
+
+      apiFetch({
+        path: path
+      }).then(function (items) {
+        _this2.setState({
+          items: items
+        });
+      }, function (error) {
+        _this2.setState({
+          error: error.message
+        });
+      });
+    }
+  }, {
+    key: "selectItemName",
+    value: function selectItemName(event, itemID) {
+      var onSelectItem = this.props.onSelectItem;
+      event.preventDefault();
+      this.setState({
+        search: '',
+        items: [],
+        error: ''
+      });
+      return onSelectItem({
+        itemID: itemID
+      });
+    }
+  }, {
+    key: "render",
+    value: function render() {
+      var _this3 = this;
+
+      var _this$state = this.state,
+          search = _this$state.search,
+          items = _this$state.items;
+      var _this$props2 = this.props,
+          ariaLabel = _this$props2.ariaLabel,
+          placeholder = _this$props2.placeholder,
+          useAvatar = _this$props2.useAvatar;
+      var itemsList;
+
+      if (!ariaLabel) {
+        ariaLabel = __('Item\'s name', 'buddypress');
+      }
+
+      if (!placeholder) {
+        placeholder = __('Enter Item\'s name here…', 'buddypress');
+      }
+
+      if (items.length) {
+        itemsList = items.map(function (item) {
+          return createElement("button", {
+            type: "button",
+            key: 'editor-autocompleters__item-item-' + item.id,
+            role: "option",
+            "aria-selected": "true",
+            className: "components-button components-autocomplete__result editor-autocompleters__user",
+            onClick: function onClick(event) {
+              return _this3.selectItemName(event, item.id);
+            }
+          }, useAvatar && createElement("img", {
+            key: "avatar",
+            className: "editor-autocompleters__user-avatar",
+            alt: "",
+            src: item.avatar_urls.thumb
+          }), createElement("span", {
+            key: "name",
+            className: "editor-autocompleters__user-name"
+          }, item.name), item.mention_name && createElement("span", {
+            key: "slug",
+            className: "editor-autocompleters__user-slug"
+          }, item.mention_name));
+        });
+      }
+
+      return createElement(Fragment, null, createElement("input", {
+        type: "text",
+        value: search,
+        className: "components-placeholder__input",
+        "aria-label": ariaLabel,
+        placeholder: placeholder,
+        onChange: function onChange(event) {
+          return _this3.searchItemName(event.target.value);
+        }
+      }), 0 !== items.length && createElement(Popover, {
+        className: "components-autocomplete__popover",
+        focusOnMount: false,
+        position: "bottom left"
+      }, createElement("div", {
+        className: "components-autocomplete__results"
+      }, itemsList)));
+    }
+  }]);
+  return BPAutocompleter;
+}(Component);
+
+var _default = BPAutocompleter;
+exports.default = _default;
+},{"@babel/runtime/helpers/classCallCheck":"kUj2","@babel/runtime/helpers/createClass":"dMjH","@babel/runtime/helpers/possibleConstructorReturn":"cbGp","@babel/runtime/helpers/getPrototypeOf":"XApn","@babel/runtime/helpers/assertThisInitialized":"oXBW","@babel/runtime/helpers/inherits":"PhTw"}],"TmUL":[function(require,module,exports) {
+"use strict";
+
+var _bpAutocompleter = _interopRequireDefault(require("../../../bp-core/js/blocks/bp-autocompleter"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * WordPress dependencies.
+ */
+var registerBlockType = wp.blocks.registerBlockType;
+var _wp$element = wp.element,
+    createElement = _wp$element.createElement,
+    Fragment = _wp$element.Fragment;
+var _wp$components = wp.components,
+    Placeholder = _wp$components.Placeholder,
+    Disabled = _wp$components.Disabled,
+    PanelBody = _wp$components.PanelBody,
+    SelectControl = _wp$components.SelectControl,
+    ToggleControl = _wp$components.ToggleControl,
+    Toolbar = _wp$components.Toolbar,
+    ToolbarButton = _wp$components.ToolbarButton;
+var _wp$blockEditor = wp.blockEditor,
+    InspectorControls = _wp$blockEditor.InspectorControls,
+    BlockControls = _wp$blockEditor.BlockControls;
+var withSelect = wp.data.withSelect;
+var compose = wp.compose.compose;
+var ServerSideRender = wp.editor.ServerSideRender;
+var __ = wp.i18n.__;
+/**
+ * Internal dependencies.
+ */
+
+var AVATAR_SIZES = [{
+  label: __('None', 'buddypress'),
+  value: 'none'
+}, {
+  label: __('Thumb', 'buddypress'),
+  value: 'thumb'
+}, {
+  label: __('Full', 'buddypress'),
+  value: 'full'
+}];
+
+var editMember = function editMember(_ref) {
+  var attributes = _ref.attributes,
+      setAttributes = _ref.setAttributes,
+      bpSettings = _ref.bpSettings;
+  var isAvatarEnabled = bpSettings.isAvatarEnabled,
+      isMentionEnabled = bpSettings.isMentionEnabled,
+      isCoverImageEnabled = bpSettings.isCoverImageEnabled;
+  var avatarSize = attributes.avatarSize,
+      displayMentionSlug = attributes.displayMentionSlug,
+      displayActionButton = attributes.displayActionButton,
+      displayCoverImage = attributes.displayCoverImage;
+
+  if (!attributes.itemID) {
+    return createElement(Placeholder, {
+      icon: "admin-users",
+      label: __('BuddyPress Member', 'buddypress'),
+      instructions: __('Start typing the name of the member you want to feature into this post.', 'buddypress')
+    }, createElement(_bpAutocompleter.default, {
+      component: "members",
+      ariaLabel: __('Member\'s username', 'buddypress'),
+      placeholder: __('Enter Member\'s username here…', 'buddypress'),
+      onSelectItem: setAttributes,
+      useAvatar: isAvatarEnabled
+    }));
+  }
+
+  return createElement(Fragment, null, createElement(BlockControls, null, createElement(Toolbar, null, createElement(ToolbarButton, {
+    icon: "edit",
+    title: __('Select another member', 'buddypress'),
+    onClick: function onClick() {
+      setAttributes({
+        itemID: 0
+      });
+    }
+  }))), createElement(InspectorControls, null, createElement(PanelBody, {
+    title: __('Profile button settings', 'buddypress'),
+    initialOpen: true
+  }, createElement(ToggleControl, {
+    label: __('Display Profile button', 'buddypress'),
+    checked: !!displayActionButton,
+    onChange: function onChange() {
+      setAttributes({
+        displayActionButton: !displayActionButton
+      });
+    },
+    help: displayActionButton ? __('Include a link to the user\'s profile page under their display name.', 'buddypress') : __('Toggle to display a link to the user\'s profile page under their display name.', 'buddypress')
+  })), isAvatarEnabled && createElement(PanelBody, {
+    title: __('Avatar settings', 'buddypress'),
+    initialOpen: false
+  }, createElement(SelectControl, {
+    label: __('Size', 'buddypress'),
+    value: avatarSize,
+    options: AVATAR_SIZES,
+    onChange: function onChange(option) {
+      setAttributes({
+        avatarSize: option
+      });
+    }
+  })), isCoverImageEnabled && createElement(PanelBody, {
+    title: __('Cover image settings', 'buddypress'),
+    initialOpen: false
+  }, createElement(ToggleControl, {
+    label: __('Display Cover Image', 'buddypress'),
+    checked: !!displayCoverImage,
+    onChange: function onChange() {
+      setAttributes({
+        displayCoverImage: !displayCoverImage
+      });
+    },
+    help: displayCoverImage ? __('Include the user\'s cover image over their display name.', 'buddypress') : __('Toggle to display the user\'s cover image over their display name.', 'buddypress')
+  })), isMentionEnabled && createElement(PanelBody, {
+    title: __('Mention settings', 'buddypress'),
+    initialOpen: false
+  }, createElement(ToggleControl, {
+    label: __('Display Mention slug', 'buddypress'),
+    checked: !!displayMentionSlug,
+    onChange: function onChange() {
+      setAttributes({
+        displayMentionSlug: !displayMentionSlug
+      });
+    },
+    help: displayMentionSlug ? __('Include the user\'s mention name under their display name.', 'buddypress') : __('Toggle to display the user\'s mention name under their display name.', 'buddypress')
+  }))), createElement(Disabled, null, createElement(ServerSideRender, {
+    block: "bp/member",
+    attributes: attributes
+  })));
+};
+
+var editMemberBlock = compose([withSelect(function (select) {
+  var editorSettings = select('core/editor').getEditorSettings();
+  return {
+    bpSettings: editorSettings.bp.members || {}
+  };
+})])(editMember);
+registerBlockType('bp/member', {
+  title: __('Member', 'buddypress'),
+  description: __('BuddyPress Member.', 'buddypress'),
+  icon: 'admin-users',
+  category: 'buddypress',
+  attributes: {
+    itemID: {
+      type: 'integer',
+      default: 0
+    },
+    avatarSize: {
+      type: 'string',
+      default: 'full'
+    },
+    displayMentionSlug: {
+      type: 'boolean',
+      default: true
+    },
+    displayActionButton: {
+      type: 'boolean',
+      default: true
+    },
+    displayCoverImage: {
+      type: 'boolean',
+      default: true
+    }
+  },
+  edit: editMemberBlock
+});
+},{"../../../bp-core/js/blocks/bp-autocompleter":"xHsb"}]},{},["TmUL"], null)
\ No newline at end of file
diff --git src/class-buddypress.php src/class-buddypress.php
index a5d449ebd..e4e559eae 100644
--- src/class-buddypress.php
+++ src/class-buddypress.php
@@ -488,6 +488,7 @@ class BuddyPress {
 		require( $this->plugin_dir . 'bp-core/bp-core-loader.php'           );
 		require( $this->plugin_dir . 'bp-core/bp-core-customizer-email.php' );
 		require( $this->plugin_dir . 'bp-core/bp-core-rest-api.php'         );
+		require( $this->plugin_dir . 'bp-core/bp-core-blocks.php'           );
 
 		// Maybe load deprecated functionality (this double negative is proof positive!).
 		if ( ! bp_get_option( '_bp_ignore_deprecated_code', ! $this->load_deprecated ) ) {
@@ -554,6 +555,7 @@ class BuddyPress {
 			'BP_Attachment_Cover_Image'                  => 'core',
 			'BP_Attachment'                              => 'core',
 			'BP_Button'                                  => 'core',
+			'BP_Block'                                   => 'core',
 			'BP_Component'                               => 'core',
 			'BP_Customizer_Control_Range'                => 'core',
 			'BP_Date_Query'                              => 'core',
diff --git src/js/bp-core/js/blocks/.babelrc src/js/bp-core/js/blocks/.babelrc
new file mode 100644
index 000000000..ab258a69c
--- /dev/null
+++ src/js/bp-core/js/blocks/.babelrc
@@ -0,0 +1,3 @@
+{
+	"presets": ["@wordpress/default"]
+}
diff --git src/js/bp-core/js/blocks/bp-autocompleter.js src/js/bp-core/js/blocks/bp-autocompleter.js
new file mode 100644
index 000000000..6c8ca3d04
--- /dev/null
+++ src/js/bp-core/js/blocks/bp-autocompleter.js
@@ -0,0 +1,124 @@
+/**
+ * WordPress dependencies.
+ */
+const { Component, Fragment, createElement } = wp.element;
+const { Popover } = wp.components;
+const { apiFetch } = wp;
+const { __ } = wp.i18n;
+
+class BPAutocompleter extends Component {
+	constructor() {
+		super( ...arguments );
+
+		this.state = {
+			search: '',
+			items: [],
+			error: '',
+		};
+
+		this.searchItemName = this.searchItemName.bind( this );
+		this.selectItemName = this.selectItemName.bind( this );
+	}
+
+	searchItemName( value ) {
+		const { search } = this.state;
+		const { component, objectStatus } = this.props;
+		this.setState( { search: value } );
+
+		if ( value.length < search.length ) {
+			this.setState( { items: [] } );
+		}
+
+		let path= '/buddypress/v1/' + component;
+
+		if ( value ) {
+			path += '?search=' + encodeURIComponent( value );
+		}
+
+		if ( objectStatus ) {
+			path += '&status=' + objectStatus;
+		}
+
+		apiFetch( { path:  path } ).then( items => {
+			this.setState( { items: items } );
+		}, error => {
+			this.setState( { error: error.message } );
+		} );
+	}
+
+	selectItemName( event, itemID ) {
+		const { onSelectItem } = this.props;
+		event.preventDefault();
+
+		this.setState( {
+			search: '',
+			items: [],
+			error: '',
+		} );
+
+		return onSelectItem( { itemID: itemID } );
+	}
+
+	render() {
+		const { search, items } = this.state;
+		let { ariaLabel, placeholder, useAvatar } = this.props;
+		let itemsList;
+
+		if ( ! ariaLabel ) {
+			ariaLabel = __( 'Item\'s name', 'buddypress' );
+		}
+
+		if ( ! placeholder ) {
+			placeholder = __( 'Enter Item\'s name here…', 'buddypress' );
+		}
+
+		if ( items.length ) {
+			itemsList = items.map( ( item ) => {
+				return (
+					<button
+						type="button" key={ 'editor-autocompleters__item-item-' + item.id }
+						role="option"
+						aria-selected="true"
+						className="components-button components-autocomplete__result editor-autocompleters__user"
+						onClick={ ( event ) => this.selectItemName( event, item.id ) }
+					>
+						{ useAvatar && (
+							<img key="avatar" className="editor-autocompleters__user-avatar" alt="" src={ item.avatar_urls.thumb } />
+						) }
+						<span key="name" className="editor-autocompleters__user-name">{ item.name }</span>
+
+						{ item.mention_name && (
+							<span key="slug" className="editor-autocompleters__user-slug">{ item.mention_name }</span>
+						) }
+					</button>
+				);
+			} );
+		}
+
+		return (
+			<Fragment>
+				<input
+					type="text"
+					value={ search }
+					className="components-placeholder__input"
+					aria-label={ ariaLabel }
+					placeholder={ placeholder }
+					onChange={ ( event ) => this.searchItemName( event.target.value ) }
+				/>
+				{ 0 !== items.length &&
+					<Popover
+						className="components-autocomplete__popover"
+						focusOnMount={ false }
+						position="bottom left"
+					>
+						<div className="components-autocomplete__results">
+							{ itemsList }
+						</div>
+					</Popover>
+				}
+			</Fragment>
+		);
+	}
+}
+
+export default BPAutocompleter;
diff --git src/js/bp-groups/js/blocks/.babelrc src/js/bp-groups/js/blocks/.babelrc
new file mode 100644
index 000000000..ab258a69c
--- /dev/null
+++ src/js/bp-groups/js/blocks/.babelrc
@@ -0,0 +1,3 @@
+{
+	"presets": ["@wordpress/default"]
+}
diff --git src/js/bp-groups/js/blocks/group.js src/js/bp-groups/js/blocks/group.js
new file mode 100644
index 000000000..5fa40674e
--- /dev/null
+++ src/js/bp-groups/js/blocks/group.js
@@ -0,0 +1,176 @@
+/**
+ * WordPress dependencies.
+ */
+const { registerBlockType } = wp.blocks;
+const { createElement, Fragment } = wp.element;
+const { Placeholder, Disabled, PanelBody, SelectControl, ToggleControl, Toolbar, ToolbarButton } = wp.components;
+const { InspectorControls, BlockControls } = wp.blockEditor;
+const { withSelect } = wp.data;
+const { compose } = wp.compose;
+const { ServerSideRender } = wp.editor;
+const { __ } = wp.i18n;
+
+/**
+ * Internal dependencies.
+ */
+import BPAutocompleter from '../../../bp-core/js/blocks/bp-autocompleter';
+
+const AVATAR_SIZES = [
+	{
+		label: __( 'None', 'buddypress' ),
+		value: 'none',
+	},
+	{
+		label: __( 'Thumb', 'buddypress' ),
+		value: 'thumb',
+	},
+	{
+		label: __( 'Full', 'buddypress' ),
+		value: 'full',
+	},
+];
+
+const editGroup = ( { attributes, setAttributes, bpSettings } ) => {
+	const { isAvatarEnabled, isCoverImageEnabled } = bpSettings;
+	const { avatarSize, displayDescription, displayActionButton, displayCoverImage } = attributes;
+
+	if ( ! attributes.itemID ) {
+		return (
+			<Placeholder
+				icon="buddicons-groups"
+				label={ __( 'BuddyPress Group', 'buddypress' ) }
+				instructions={ __( 'Start typing the name of the group you want to feature into this post.', 'buddypress' ) }
+			>
+				<BPAutocompleter
+					component="groups"
+					objectStatus="public"
+					ariaLabel={ __( 'Group\'s name', 'buddypress' ) }
+					placeholder={ __( 'Enter Group\'s name here…', 'buddypress' ) }
+					onSelectItem={ setAttributes }
+					useAvatar={ isAvatarEnabled }
+				/>
+			</Placeholder>
+		);
+	}
+
+	return (
+		<Fragment>
+			<BlockControls>
+				<Toolbar>
+					<ToolbarButton
+						icon="edit"
+						title={ __( 'Select another group', 'buddypress' ) }
+						onClick={ () =>{
+							setAttributes( { itemID: 0 } );
+						} }
+					/>
+				</Toolbar>
+			</BlockControls>
+			<InspectorControls>
+				<PanelBody title={ __( 'Group\'s home button settings', 'buddypress' ) } initialOpen={ true }>
+					<ToggleControl
+						label={ __( 'Display Group\'s home button', 'buddypress' ) }
+						checked={ !! displayActionButton }
+						onChange={ () => {
+							setAttributes( { displayActionButton: ! displayActionButton } );
+						} }
+						help={
+							displayActionButton
+								? __( 'Include a link to the group\'s home page under their name.', 'buddypress' )
+								: __( 'Toggle to display a link to the group\'s home page under their name.', 'buddypress' )
+						}
+					/>
+				</PanelBody>
+				<PanelBody title={ __( 'Description settings', 'buddypress' ) } initialOpen={ false }>
+					<ToggleControl
+						label={ __( 'Display group\'s description', 'buddypress' ) }
+						checked={ !! displayDescription }
+						onChange={ () => {
+							setAttributes( { displayDescription: ! displayDescription } );
+						} }
+						help={
+							displayDescription
+								? __( 'Include the group\'s description under their name.', 'buddypress' )
+								: __( 'Toggle to display the group\'s description under their name.', 'buddypress' )
+						}
+					/>
+				</PanelBody>
+				{ isAvatarEnabled && (
+					<PanelBody title={ __( 'Avatar settings', 'buddypress' ) } initialOpen={ false }>
+						<SelectControl
+							label={ __( 'Size', 'buddypress' ) }
+							value={ avatarSize }
+							options={ AVATAR_SIZES }
+							onChange={ ( option ) => {
+								setAttributes( { avatarSize: option } );
+							} }
+						/>
+					</PanelBody>
+				) }
+				{ isCoverImageEnabled && (
+					<PanelBody title={ __( 'Cover image settings', 'buddypress' ) } initialOpen={ false }>
+						<ToggleControl
+							label={ __( 'Display Cover Image', 'buddypress' ) }
+							checked={ !! displayCoverImage }
+							onChange={ () => {
+								setAttributes( { displayCoverImage: ! displayCoverImage } );
+							} }
+							help={
+								displayCoverImage
+									? __( 'Include the group\'s cover image over their name.', 'buddypress' )
+									: __( 'Toggle to display the group\'s cover image over their name.', 'buddypress' )
+							}
+						/>
+					</PanelBody>
+				) }
+			</InspectorControls>
+			<Disabled>
+				<ServerSideRender block="bp/group" attributes={ attributes } />
+			</Disabled>
+		</Fragment>
+	);
+};
+
+const editGroupBlock = compose( [
+	withSelect( ( select ) => {
+		const editorSettings = select( 'core/editor' ).getEditorSettings();
+		return {
+			bpSettings: editorSettings.bp.groups || {},
+		};
+	} ),
+] )( editGroup );
+
+registerBlockType( 'bp/group', {
+	title: __( 'Group', 'buddypress' ),
+
+	description: __( 'BuddyPress Group.', 'buddypress' ),
+
+	icon: 'buddicons-groups',
+
+	category: 'buddypress',
+
+	attributes: {
+		itemID: {
+			type: 'integer',
+			default: 0,
+		},
+		avatarSize: {
+			type: 'string',
+			default: 'full',
+		},
+		displayDescription: {
+			type: 'boolean',
+			default: true,
+		},
+		displayActionButton: {
+			type: 'boolean',
+			default: true,
+		},
+		displayCoverImage: {
+			type: 'boolean',
+			default: true,
+		},
+	},
+
+	edit: editGroupBlock,
+} );
diff --git src/js/bp-members/js/blocks/.babelrc src/js/bp-members/js/blocks/.babelrc
new file mode 100644
index 000000000..ab258a69c
--- /dev/null
+++ src/js/bp-members/js/blocks/.babelrc
@@ -0,0 +1,3 @@
+{
+	"presets": ["@wordpress/default"]
+}
diff --git src/js/bp-members/js/blocks/member.js src/js/bp-members/js/blocks/member.js
new file mode 100644
index 000000000..179a61dbb
--- /dev/null
+++ src/js/bp-members/js/blocks/member.js
@@ -0,0 +1,177 @@
+/**
+ * WordPress dependencies.
+ */
+const { registerBlockType } = wp.blocks;
+const { createElement, Fragment } = wp.element;
+const { Placeholder, Disabled, PanelBody, SelectControl, ToggleControl, Toolbar, ToolbarButton } = wp.components;
+const { InspectorControls, BlockControls } = wp.blockEditor;
+const { withSelect } = wp.data;
+const { compose } = wp.compose;
+const { ServerSideRender } = wp.editor;
+const { __ } = wp.i18n;
+
+/**
+ * Internal dependencies.
+ */
+import BPAutocompleter from '../../../bp-core/js/blocks/bp-autocompleter';
+
+const AVATAR_SIZES = [
+	{
+		label: __( 'None', 'buddypress' ),
+		value: 'none',
+	},
+	{
+		label: __( 'Thumb', 'buddypress' ),
+		value: 'thumb',
+	},
+	{
+		label: __( 'Full', 'buddypress' ),
+		value: 'full',
+	},
+];
+
+const editMember = ( { attributes, setAttributes, bpSettings } ) => {
+	const { isAvatarEnabled, isMentionEnabled, isCoverImageEnabled } = bpSettings;
+	const { avatarSize, displayMentionSlug, displayActionButton, displayCoverImage } = attributes;
+
+	if ( ! attributes.itemID ) {
+		return (
+			<Placeholder
+				icon="admin-users"
+				label={ __( 'BuddyPress Member', 'buddypress' ) }
+				instructions={ __( 'Start typing the name of the member you want to feature into this post.', 'buddypress' ) }
+			>
+				<BPAutocompleter
+					component="members"
+					ariaLabel={ __( 'Member\'s username', 'buddypress' ) }
+					placeholder={ __( 'Enter Member\'s username here…', 'buddypress' ) }
+					onSelectItem={ setAttributes }
+					useAvatar={ isAvatarEnabled }
+				/>
+			</Placeholder>
+		);
+	}
+
+	return (
+		<Fragment>
+			<BlockControls>
+				<Toolbar>
+					<ToolbarButton
+						icon="edit"
+						title={ __( 'Select another member', 'buddypress' ) }
+						onClick={ () =>{
+							setAttributes( { itemID: 0 } );
+						} }
+					/>
+				</Toolbar>
+			</BlockControls>
+			<InspectorControls>
+				<PanelBody title={ __( 'Profile button settings', 'buddypress' ) } initialOpen={ true }>
+					<ToggleControl
+						label={ __( 'Display Profile button', 'buddypress' ) }
+						checked={ !! displayActionButton }
+						onChange={ () => {
+							setAttributes( { displayActionButton: ! displayActionButton } );
+						} }
+						help={
+							displayActionButton
+								? __( 'Include a link to the user\'s profile page under their display name.', 'buddypress' )
+								: __( 'Toggle to display a link to the user\'s profile page under their display name.', 'buddypress' )
+						}
+					/>
+				</PanelBody>
+				{ isAvatarEnabled && (
+					<PanelBody title={ __( 'Avatar settings', 'buddypress' ) } initialOpen={ false }>
+						<SelectControl
+							label={ __( 'Size', 'buddypress' ) }
+							value={ avatarSize }
+							options={ AVATAR_SIZES }
+							onChange={ ( option ) => {
+								setAttributes( { avatarSize: option } );
+							} }
+						/>
+					</PanelBody>
+				) }
+				{ isCoverImageEnabled && (
+					<PanelBody title={ __( 'Cover image settings', 'buddypress' ) } initialOpen={ false }>
+						<ToggleControl
+							label={ __( 'Display Cover Image', 'buddypress' ) }
+							checked={ !! displayCoverImage }
+							onChange={ () => {
+								setAttributes( { displayCoverImage: ! displayCoverImage } );
+							} }
+							help={
+								displayCoverImage
+									? __( 'Include the user\'s cover image over their display name.', 'buddypress' )
+									: __( 'Toggle to display the user\'s cover image over their display name.', 'buddypress' )
+							}
+						/>
+					</PanelBody>
+				) }
+				{ isMentionEnabled && (
+					<PanelBody title={ __( 'Mention settings', 'buddypress' ) } initialOpen={ false }>
+						<ToggleControl
+							label={ __( 'Display Mention slug', 'buddypress' ) }
+							checked={ !! displayMentionSlug }
+							onChange={ () => {
+								setAttributes( { displayMentionSlug: ! displayMentionSlug } );
+							} }
+							help={
+								displayMentionSlug
+									? __( 'Include the user\'s mention name under their display name.', 'buddypress' )
+									: __( 'Toggle to display the user\'s mention name under their display name.', 'buddypress' )
+							}
+						/>
+					</PanelBody>
+				) }
+			</InspectorControls>
+			<Disabled>
+				<ServerSideRender block="bp/member" attributes={ attributes } />
+			</Disabled>
+		</Fragment>
+	);
+};
+
+const editMemberBlock = compose( [
+	withSelect( ( select ) => {
+		const editorSettings = select( 'core/editor' ).getEditorSettings();
+		return {
+			bpSettings: editorSettings.bp.members || {},
+		};
+	} ),
+] )( editMember );
+
+registerBlockType( 'bp/member', {
+	title: __( 'Member', 'buddypress' ),
+
+	description: __( 'BuddyPress Member.', 'buddypress' ),
+
+	icon: 'admin-users',
+
+	category: 'buddypress',
+
+	attributes: {
+		itemID: {
+			type: 'integer',
+			default: 0,
+		},
+		avatarSize: {
+			type: 'string',
+			default: 'full',
+		},
+		displayMentionSlug: {
+			type: 'boolean',
+			default: true,
+		},
+		displayActionButton: {
+			type: 'boolean',
+			default: true,
+		},
+		displayCoverImage: {
+			type: 'boolean',
+			default: true,
+		},
+	},
+
+	edit: editMemberBlock,
+} );
