CINXE.COM
Groups.io: Features
<!DOCTYPE html> <html lang="en-US"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> <meta name="3778517eb4810dfb5d143ed8f1b359b3b5a82923" content="0f56257c3db4a222e91b11bc6871c4df2e263b28" /> <link rel="apple-touch-icon" sizes="57x57" href="/img/org.1/favicons/apple-icon-57x57.png"> <link rel="apple-touch-icon" sizes="60x60" href="/img/org.1/favicons/apple-icon-60x60.png"> <link rel="apple-touch-icon" sizes="72x72" href="/img/org.1/favicons/apple-icon-72x72.png"> <link rel="apple-touch-icon" sizes="76x76" href="/img/org.1/favicons/apple-icon-76x76.png"> <link rel="apple-touch-icon" sizes="114x114" href="/img/org.1/favicons/apple-icon-114x114.png"> <link rel="apple-touch-icon" sizes="120x120" href="/img/org.1/favicons/apple-icon-120x120.png"> <link rel="apple-touch-icon" sizes="144x144" href="/img/org.1/favicons/apple-icon-144x144.png"> <link rel="apple-touch-icon" sizes="152x152" href="/img/org.1/favicons/apple-icon-152x152.png"> <link rel="apple-touch-icon" sizes="180x180" href="/img/org.1/favicons/apple-icon-180x180.png"> <link rel="icon" type="image/png" sizes="192x192" href="/img/org.1/favicons/android-icon-192x192.png"> <link rel="icon" type="image/png" sizes="32x32" href="/img/org.1/favicons/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="96x96" href="/img/org.1/favicons/favicon-96x96.png"> <link rel="icon" type="image/png" sizes="16x16" href="/img/org.1/favicons/favicon-16x16.png"> <link rel="manifest" href="/img/org.1/favicons/manifest.json"> <meta name="msapplication-TileColor" content="#ffffff"> <meta name="msapplication-TileImage" content="/ms-icon-144x144.png"> <script> /* stubs */ const hapticsImpactHeavy = async () => { }; const hapticsImpactMedium = async () => { }; const hapticsImpactLight = async () => { }; const hapticsVibrate = async () => { }; const hapticsSelectionStart = async () => { }; const hapticsSelectionChanged = async () => { }; const hapticsSelectionEnd = async () => { }; </script> <script> function setPullToRefresh() {} function gotoURL(inurl) { window.location.href = inurl; return; } function contentLoaded(isHTMX, f, caller = "") { console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { if (document.readyState !== 'loading') { console.log('document is already ready, just execute code here'); f(); } else { console.log('document was not ready, place code here'); document.addEventListener('DOMContentLoaded', f, {once: true}); } } } function HideAppSidebarOnKeyboard() { console.log("In HideAppSidebarOnKeyboard"); } // stub function logError(data, url, linenumber) { console.log(data) return; } var pushSubToken; var ignoreErrors = false; var lastError = ""; window.onerror = function(errorMessage, errorUrl, errorLine, errorColumn, errorObj) { let column; let stack; if (console && console.log) { console.log("msg:", errorMessage); console.log("url:", errorUrl); console.log("line:", errorLine); if (errorColumn !== undefined && errorObj != null) { console.log("column:", errorColumn); column = errorColumn; } if (errorObj !== undefined && errorObj != null) { console.log("stack:", errorObj.stack); stack = errorObj.stack; } console.log("client_id:", "web.web08.9809384.1740273367877988628"); console.log("last_error:", lastError); console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; } if (errorMessage.includes("SecurityError:") == true) { ignoreErrors = true; } if (ignoreErrors == true) { console.log("cookies, disabled, ignoring"); lastError = errorMessage; return; } jQuery.ajax({ type: 'POST', url: '/jsclienterror', data: { msg: errorMessage, url: errorUrl, line: errorLine, column: column, stack: stack, last_error: lastError, client_id: "web.web08.9809384.1740273367877988628" }, success: function() { if (console && console.log) { console.log('JS error report successful.'); } lastError = errorMessage; }, error: function() { if (console && console.error) { console.error('JS error report submission failed!'); } lastError = errorMessage; } }); return true; } </script> <script src="/tinymce-5.10.9/tinymce.min.js"></script> <script src="/js/browser-image-compression-2.0.2.min.js"></script> <link href="/css/application-ddb8b9131d6cc3df6479ea15af05e501.css" rel="stylesheet" id="groupsio-css"> <script src="/js/application-9b2c27b802a13063cf8a712fe566f004.js" id="groupsio-js"></script> <script src="/js/run_prettify.js"></script> <title>Groups.io: Features</title> <script> htmx.config.scrollBehavior = "instant"; htmx.config.historyCacheSize = 0; htmx.config.defaultSettleDelay = 0; console.log("FULL PAGE LOAD"); </script> </head> <body id="body" class="" hx-headers='{"Accept-Version": "40ba648cd09c24c9d0a77c28ad33139613317e9d"}' hx-ext="preload" hx-boost="false"> <script> if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { document.body.classList.add('dark-mode'); } </script> <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left" hx-boost="false" hx-disinherit="*"> <img src="https://groups.io/img/org.1/mainlogo.png?cachebust" height="50" alt="Groups.io"> </a> <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> Find or Create a Group </a> </li> </ul> <ul class="nav navbar-nav pull-right visible-xs" style="margin-top:5px;margin-bottom:5px;"> <li> <a href="#" data-toggle="modal" data-target="#mobileAccount"> <i class="fa-fw fa fa-bars fa-lg"></i> </a> </li> </ul> <ul class="nav navbar-nav pull-right hidden-xs"> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <i class="fa-fw fa-regular fa-globe"></i> EN <b class="caret"></b> </a> <ul class="dropdown-menu"> <li> <a href="https://groups.io/unsetlang"> EN </a> </li> <li> <a href="https://groups.io/setlang/de"> DE </a> </li> <li> <a href="https://groups.io/setlang/es"> ES </a> </li> <li> <a href="https://groups.io/setlang/fr"> FR </a> </li> <li> <a href="https://groups.io/setlang/it"> IT </a> </li> <li> <a href="https://groups.io/setlang/pt"> PT </a> </li> <li> <a href="https://groups.io/setlang/uk"> UK </a> </li> </ul> </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> Help </a> </li> <li> <a href="https://groups.io/login" hx-boost="false" hx-disinherit="*"> <i class="fa fa-sign-in-alt"></i> Log In </a> </li> <li> <a href="https://groups.io/register"> <i class="fa fa-user"></i> Sign Up </a> </li> </ul> </div> </div> <div class="modal fade" id="mobileAccount" role="dialog"> <div class="modal-dialog" style="margin-top:50px;"> <div class="modal-content"> <div class="modal-body"> <ul class="list-group noborderlist"> <li class="noborderitem list-group-item"> <a href="https://groups.io/login" hx-boost="false" hx-disinherit="*"> <i class="fa fa-sign-in-alt"></i> Log In </a> </li> <li class="noborderitem list-group-item"> <a href="https://groups.io/register"> <i class="fa fa-user"></i> Sign Up </a> </li> <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> <li class="dropdown noborderitem list-group-item"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <i class="fa-fw fa-regular fa-globe"></i> EN <b class="caret"></b> </a> <ul class="dropdown-menu"> <li> <a href="https://groups.io/unsetlang"> EN </a> </li> <li> <a href="https://groups.io/setlang/de"> DE </a> </li> <li> <a href="https://groups.io/setlang/es"> ES </a> </li> <li> <a href="https://groups.io/setlang/fr"> FR </a> </li> <li> <a href="https://groups.io/setlang/it"> IT </a> </li> <li> <a href="https://groups.io/setlang/pt"> PT </a> </li> <li> <a href="https://groups.io/setlang/uk"> UK </a> </li> </ul> </li> </ul> </div> </div> </div> </div> <script> var groupnavigatorData = [ ]; </script> <!-- Modal Dialog for Autocomplete --> <div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-body"> <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate <i class="fa-sharp fa-arrow-turn-down-left"></i> to use <strong>esc</strong> to dismiss</div> </div> </div> </div> </div> <script> // Keep track of the currently selected index var selectedIndex = -1; // Function to highlight the matched substring function highlightSubstring(str, substring) { var index = str.toLowerCase().indexOf(substring.toLowerCase()); if (index !== -1) { var before = str.substring(0, index); var middle = str.substring(index, index + substring.length); var after = str.substring(index + substring.length); return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; } return str; } // Function to highlight the selected item and ensure it is visible in the scrollable list function highlightSelectedItem(modalName) { var listContainer = document.getElementById(modalName + 'Container'); var items = document.getElementsByClassName(modalName + '-list-item'); Array.from(items).forEach(function(item, idx) { item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item }); if (items.length > 0 && selectedIndex >= 0) { var selectedItem = items[selectedIndex]; var containerTop = listContainer.scrollTop; var containerBottom = containerTop + listContainer.clientHeight; var itemTop = selectedItem.offsetTop; var itemBottom = itemTop + selectedItem.offsetHeight; const fudge = 59; if (selectedIndex > 0 && itemTop > containerBottom) { // If there are items below the selected item and the selected item is not fully visible, scroll down listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { // If there are items above the selected item and the selected item is not fully visible, scroll up listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; } } } // function to populate the list based on the input function populateList(modalName, data) { var input = document.getElementById(modalName+'Input').value; var listContainer = document.getElementById(modalName+'Container'); listContainer.innerHTML = ''; data.forEach(function(item) { if (item.name.toLowerCase().includes(input.toLowerCase())) { var div = document.createElement('div'); div.innerHTML = highlightSubstring(item.name, input); div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class div.addEventListener('click', function() { // Navigate to the specified URL when a list item is clicked window.location.href = item.url; }); div.addEventListener('mousemove', function() { // Remove no-hover class from all items when the mouse is moved over any item console.log("mouse move"); var items = document.getElementsByClassName(modalName+'-list-item'); Array.from(items).forEach(function(item) { item.classList.remove('no-hover'); }); }); listContainer.appendChild(div); } }); highlightSelectedItem(modalName); } function InitAutocomplete(modalName, data) { // Focus the input field when the modal is shown and populate the list $('#' + modalName + 'Modal').on('shown.bs.modal', function () { $('#' + modalName + 'Input').focus().val(''); populateList(modalName, data); selectedIndex = 0; highlightSelectedItem(modalName); }); // Event listener for input field typing document.getElementById(modalName + 'Input').addEventListener('input', function() { populateList(modalName, data); selectedIndex = 0; }); // Event listener for arrow keys and enter key document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { var items = document.getElementsByClassName(modalName + '-list-item'); if (event.key === 'ArrowDown') { event.preventDefault(); if (selectedIndex < items.length - 1) selectedIndex++; highlightSelectedItem(modalName); } else if (event.key === 'ArrowUp') { event.preventDefault(); if (selectedIndex > 0) selectedIndex--; highlightSelectedItem(modalName); } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { event.preventDefault(); items[selectedIndex].click(); } }); } function showAutocompleteModal(modalName) { $('#' + modalName + 'Modal').modal('show'); selectedIndex = -1; } </script> <div id="content" class="container-fluid"> <script> InitAutocomplete("groupnavigator", groupnavigatorData); document.body.addEventListener("showReloadPageDialog", function(evt) { console.log("Forced reload"); location.reload(); }); function ShowBackButton(label) { var logoElement = document.getElementById("logo"); if (logoElement) { html = ` <span style="color:#fff;margin-top:14px;margin-left:12px;float:left !important; height:36px;"> <a onclick="goBack()" style="color:#fff"> <i class="fa-fw fa-solid fa-chevron-left fa-lg"></i> </a></span>`; if (label != "") { html += `<div style="position:absolute;left:50%;transform:translateX(-50%);text-align:center;color:#ecf0f1;margin-top:5px;"><h4>` + label + `</h4></div>`; } logoElement.innerHTML = html; } } function HideBackButton() { var logoElement = document.getElementById("logo"); if (logoElement) { logoElement.innerHTML = ` <a href="https://groups.io" class="navbar-left"> <img src="https://groups.io/img/org.1/mainlogo.png?cachebust" height="50" alt="Groups.io"> </a>`; } } function goBack() { history.back(); } // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); if (ele.startsWith('#')) { ele = ele.slice(1); } document.getElementById(ele).submit(); return; /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true }); if (typeof ele === 'string' || ele instanceof String) { if (ele.startsWith("#") == true) { ele = ele.slice(1); } if (document.getElementById(ele).dispatchEvent(theEvent) == true) { // if not cancelled, do normal submit console.log("calling submit"); document.getElementById(ele).submit(); } return; } // assume ele is the element if (ele.dispatchEvent(theEvent) == true) { // if not cancelled, do normal submit console.log("calling submit"); ele.submit(); } */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { let internalGioDestroy = function(evt) { // do not activate on infinite scroll events if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { console.log("Ignoring infinite scroll event"); return; } console.log("Calling destroy callback"); eventCB(evt); } document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); } var drawerCloseFunc = function(evt) { console.log("in drawerCloseFunc"); // Find all elements with the class 'drawer' var drawers = document.querySelectorAll('.drawer'); // Iterate over each element and call closeDrawer() on each drawers.forEach(function(obj) { drawerObj.closeDrawer(obj); }); $('.modal').modal('hide'); } document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); var keydownFunc = function(event) { var tagName = event.target.tagName.toLowerCase(); if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { if (event.key === 'Escape') { event.target.blur(); } return; } // check if the viewimages viewer is up let element = document.getElementById('overlay'); if (element && element.classList.contains('visible')) { return; } console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { event.preventDefault(); // Prevent the default action // Show the modal dialog for keyboard shortcuts $('#shortcutModal').modal('show'); return; } $('#shortcutModal').modal('hide'); if (event.key.toLowerCase() === 'g') { // For Windows and Linux if (event.ctrlKey) { event.preventDefault(); showAutocompleteModal("groupnavigator"); return; } } // Check if the pressed key is '/' if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { if (event.metaKey) { event.preventDefault(); // Prevent the default action // Focus on the search box let box = document.getElementById('searchbox') if (box != null) { document.getElementById('searchbox').focus(); } } } else { // For Windows and Linux if (event.ctrlKey) { event.preventDefault(); // Prevent the default action // Focus on the search box let box = document.getElementById('searchbox') if (box != null) { document.getElementById('searchbox').focus(); } } } } } document.addEventListener('keydown', keydownFunc); var removeDrawerCloseFunc = function(evt) { document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); document.removeEventListener('keydown', keydownFunc); } document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> <!-- Modal Dialog for Keyboard Shortcuts --> <div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> :</div> <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> </div> <div class="row"> <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>g</strong> :</div> <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> </div> <div class="row"> <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong> :</div> <div class="col-xs-9" style="margin-left: -23px;">Find</div> </div> <div class="row"> <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong> :</div> <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> </div> </div> <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> </div> </div> </div> <div id="alertdiv"></div> <div class="noticetemplate template"> <div class="alert alert-success alert-dismissible" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true"> × </span> </button> <span class="flashmsg"></span> </div> </div> <div class="alerttemplate template"> <div class="alert alert-danger alert-dismissible" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true"> × </span> </button> <span class="flashmsg"></span> </div> </div> <div class="alertnoclosetemplate template"> <div class="alert alert-danger" role="alert"> <span class="flashmsg"></span> </div> </div> <script> function dismiss() { console.log("dismiss"); $.get( "/dismissalert"); } var $alerttemplate = $(".alerttemplate"); var $alertnoclosetemplate = $(".alertnoclosetemplate"); var $noticetemplate = $(".noticetemplate"); function createAlert(msg, isError, autoClose, noClose) { if (isError == false) { $newPanel = $noticetemplate.clone(); } else { if (noClose) { $newPanel = $alertnoclosetemplate.clone(); } else { $newPanel = $alerttemplate.clone(); } } $newPanel.find(".flashmsg").html(msg); if (autoClose == true) { $("#alertdiv").append($newPanel.fadeTo(2000, 500).slideUp(500, function(){ $newPanel.slideUp(500); $newPanel.remove(); })); } else { $("#alertdiv").append($newPanel.fadeIn()); } return $newPanel; } </script> <div class="col-md-offset-2 col-md-8" style="padding-bottom:20px;"> <table style="width:100%; table-layout: fixed;"> <tr> <td align="center"> <h4> <a href="/static/features"> Features </a> </h4> </td> <td align="center"> <h4> <a href="/static/pricing"> Pricing </a> </h4> </td> <td align="center"> <h4> <a href="/static/why"> Why Email Groups? </a> </h4> </td> </tr> </table> <p></p> <br> <center> <h1> The Most Advanced Features Of Any Group System </h1> </center> <br> <div class="panel panel-default"> <div class="panel-body"> <div class="row"> <div class="col-md-offset-1 col-md-10"> <p></p> <br> <center> <h1> Better archive organization with hashtags </h1> <p> Tag a message topic by including a #hashtag in the subject. </p> </center> <p></p> <br> <center> <p> Hashtags let you control and organize your archives. Tags can have an expiration; topics with those tags will be automatically deleted after the specified time. Tags can also be set as No Email, for when you want to include messages in the archive but you don't want to have them sent to the group. Tags can be restricted to a predefined set. And of course the archives are searchable by tag. </p> </center> <p></p> <br> </div> </div> </div> </div> <div class="row"> <div class="col-md-offset-1 col-md-10"> <p></p> <br> <center> <h1> Only The Messages You Want </h1> <p> Avoid email overload. </p> </center> <p></p> <br> <center> <p> You can mute individual topics and hashtags. And we have a set of powerful subscription options. You can receive every message. Or you can opt to receive only the first message in a topic, with the option to follow the topic later. Or you can opt to receive only messages in topics that you start. Finally, you can opt to receive no emails at all. </p> </center> <p></p> <br> </div> </div> <div class="row"> <div class="panel panel-default"> <div class="panel-body"> <div class="col-md-offset-1 col-md-10"> <p></p> <br> <center> <h1> Advanced group management. </h1> <p> Groups.io supports all the options you'd expect in a modern groups service. </p> </center> <p></p> <br> <center> <p> Create an announcement, moderated, or restricted group. Customize the various welcome, goodbye, monthly, and pending subscription messages. Then define multiple owners and moderators, using our full permissions system. Monitor the group through the activity log, and track email delivery to members. Approve messages from moderated users either through the website or via email. Automatically moderate or lock individual group topics after a set number of days. Relax knowing that Groups.io handles bounces and autoresponders automatically, and that we're DMARC compatible. </p> </center> <p></p> <br> </div> </div> </div> </div> <div class="row"> <div class="col-md-offset-1 col-md-10"> <p></p> <br> <center> <h1> Powerful integrations </h1> <p> Groups.io works with the services that you and your team already use. Premium groups support the following integrations: </p> </center> <p></p> <br> <ul class="list-unstyled"> <li class="featuresli"> <i class="fa-fw fa fa-envelope"></i> Email - Create a receive-only email address that posts to your group. </li> <li class="featuresli"> <i class="fa-fw fa fa-rss"></i> Feeds - Post items from RSS feeds to your group. </li> <li class="featuresli"> <i class="fa-fw fab fa-github"></i> GitHub - Post to your group whenever code is committed to a repository. </li> <li class="featuresli"> <i class="fa-fw fab fa-trello"></i> Trello - Post to your group whenever there is activity in a Trello board. </li> </ul> <p> And we're adding more integrations all the time. </p> <p></p> <br> </div> </div> <div class="panel panel-default"> <div class="panel-body"> <div class="row"> <div class="col-md-offset-1 col-md-10"> <p></p> <br> <center> <h1> Member synchronization </h1> <p> Sync your members across services. </p> </center> <p></p> <br> <center> <p> If you have a <a href="https://slack.com">Slack</a> Team, you can sync it with your Groups.io Premium group. Then, when someone joins your group, they will be automatically invited to join your Slack Team. And if someone leaves your group, they will be removed from your Slack Team. </p> </center> <p></p> <br> </div> </div> </div> </div> <div class="row"> <div class="col-md-offset-1 col-md-10"> <p></p> <br> <center> <h1> Powerful additional features </h1> <p> Messages are just the start. </p> </center> <p></p> <br> <center> <p> Each Premium group has many additional features, each of which is fully integrated with your group. Start with the calendar, where you can schedule events and send reminders. You can set up an unlimited number of chat rooms. There's also a poll feature, where you can ask questions of your group. Each group also has a full featured database, where you can define tables with different column types. There are sections for uploading photos and files. And a wiki, for storing group knowledge. Finally, each Premium group can have an unlimited number of subgroups. </p> </center> <p></p> <br> </div> </div> <p></p> <br> <center> <a class="btn btn-primary btn-lg" href="/static/pricing"> Start a Groups.io Group </a> </center> </div> </div> <div id="scroll-top-outer"> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> </div> <script> $(function() { $(document).on('scroll', function() { if ($(window).scrollTop() > 100) { $('.scroll-top-wrapper').addClass('show'); } else { $('.scroll-top-wrapper').removeClass('show'); } }); $('.scroll-top-wrapper').on('click', scrollToTop); }); function scrollToTop() { verticalOffset = typeof(verticalOffset) != 'undefined' ? verticalOffset : 0; element = $('body'); offset = element.offset(); offsetTop = offset.top; $('html, body').animate({ scrollTop: offsetTop }, 100, 'linear'); } if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { let elements = document.querySelectorAll('strong.ctrlmeta'); elements.forEach((element) => { // Check if the innerText is "ctrl" if (element.innerText === 'ctrl') { // Create a new "i" element let newElement = document.createElement('i'); newElement.classList.add('fa-solid', 'fa-command'); // Replace the old "strong" element with the new "i" element element.parentNode.replaceChild(newElement, element); } }); } </script> </body> </html>