diff --git a/invenio_communities/assets/semantic-ui/js/invenio_communities/community/header/RequestMembershipButton.js b/invenio_communities/assets/semantic-ui/js/invenio_communities/community/header/RequestMembershipButton.js
new file mode 100644
index 000000000..42c85e39f
--- /dev/null
+++ b/invenio_communities/assets/semantic-ui/js/invenio_communities/community/header/RequestMembershipButton.js
@@ -0,0 +1,104 @@
+/*
+ * This file is part of Invenio.
+ * Copyright (C) 2024 CERN.
+ * Copyright (C) 2024 Northwestern University.
+ *
+ * Invenio is free software; you can redistribute it and/or modify it
+ * under the terms of the MIT License; see LICENSE file for more details.
+ */
+
+import { i18next } from "@translations/invenio_communities/i18next";
+import { Formik } from "formik";
+import PropTypes from "prop-types";
+import React, { useState } from "react";
+import { TextAreaField } from "react-invenio-forms";
+import { Button, Form, Modal } from "semantic-ui-react";
+
+export function RequestMembershipModal(props) {
+ const { isOpen, onClose } = props;
+
+ const onSubmit = async (values, { setSubmitting, setFieldError }) => {
+ // TODO: implement me
+ console.log("RequestMembershipModal.onSubmit(args) called");
+ console.log("TODO: implement me", arguments);
+ };
+
+ let confirmed = true;
+
+ return (
+
+ {({ values, isSubmitting, handleSubmit }) => (
+
+ {i18next.t("Request Membership")}
+
+
+
+
+
+
+
+
+ )}
+
+ );
+}
+
+RequestMembershipModal.propTypes = {
+ isOpen: PropTypes.bool.isRequired,
+ onClose: PropTypes.func.isRequired,
+};
+
+export function RequestMembershipButton(props) {
+ const [isModalOpen, setModalOpen] = useState(false);
+
+ const handleClick = () => {
+ setModalOpen(true);
+ };
+
+ const handleClose = () => {
+ setModalOpen(false);
+ };
+
+ return (
+ <>
+
+ {isModalOpen && (
+
+ )}
+ >
+ );
+}
diff --git a/invenio_communities/assets/semantic-ui/js/invenio_communities/community/header/index.js b/invenio_communities/assets/semantic-ui/js/invenio_communities/community/header/index.js
new file mode 100644
index 000000000..f16b1c1f0
--- /dev/null
+++ b/invenio_communities/assets/semantic-ui/js/invenio_communities/community/header/index.js
@@ -0,0 +1,21 @@
+/*
+ * This file is part of Invenio.
+ * Copyright (C) 2024 Northwestern University.
+ *
+ * Invenio is free software; you can redistribute it and/or modify it
+ * under the terms of the MIT License; see LICENSE file for more details.
+ */
+
+import ReactDOM from "react-dom";
+
+import React from "react";
+
+import { RequestMembershipButton } from "./RequestMembershipButton";
+
+const domContainer = document.getElementById("request-membership-app");
+
+const community = JSON.parse(domContainer.dataset.community);
+
+if (domContainer) {
+ ReactDOM.render(, domContainer);
+}
diff --git a/invenio_communities/templates/semantic-ui/invenio_communities/details/base.html b/invenio_communities/templates/semantic-ui/invenio_communities/details/base.html
index 55ac48129..1f4d51eb8 100644
--- a/invenio_communities/templates/semantic-ui/invenio_communities/details/base.html
+++ b/invenio_communities/templates/semantic-ui/invenio_communities/details/base.html
@@ -9,6 +9,11 @@
{% extends "invenio_communities/base.html" %}
+{%- block javascript %}
+{{ super() }}
+{{ webpack['invenio-communities-header.js'] }}
+{%- endblock javascript %}
+
{%- block page_body %}
{% set community_menu_active = True %}
{% include "invenio_communities/details/header.html" %}
diff --git a/invenio_communities/templates/semantic-ui/invenio_communities/details/header.html b/invenio_communities/templates/semantic-ui/invenio_communities/details/header.html
index fe36a96ae..ea74b4fad 100644
--- a/invenio_communities/templates/semantic-ui/invenio_communities/details/header.html
+++ b/invenio_communities/templates/semantic-ui/invenio_communities/details/header.html
@@ -2,6 +2,7 @@
This file is part of Invenio.
Copyright (C) 2016-2020 CERN.
+ Copyright (C) 2024 Northwestern University.
Invenio is free software; you can redistribute it and/or modify it
under the terms of the MIT License; see LICENSE file for more details.
@@ -10,12 +11,25 @@
{%- from "invenio_theme/macros/truncate.html" import truncate_text %}
{%- from "invenio_communities/details/macros/access-status-label.html" import access_status_label -%}
+{% macro button_to_request_membership(community) %}
+ {# TODO: replace by permission check when permissions implemented #}
+ {% if config.COMMUNITIES_ALLOW_MEMBERSHIP_REQUESTS %}
+
+
+ {% endif %}
+{% endmacro %}
+
+