Maybe you've eared about it, the project templatejoomla.com is online since few weeks now. Today, it's the largest Joomla 4 Templates Directory so far, as 1700+ Joomla templates are already listed there. This demonstrates that the Joomla eco-system is alive, kudos guys!
Beyond numbers, I want to explain you why this project is alive, what technical decisions have been made and how we've created the Joomla Templates Directory this way. And because sharing is caring, you will be able to download a copy of the site if you want to replicate it for any kind of project (free or commercial) :)
To explain you in details all aspects of this project, I've listed here 10 questions we've received about templatejoomla.com
If you have others questions, the comment section below is open.
There are some similar directories, so why have you created this project?
The first answer to this question would be: why not?
After all, there are already themes & template directories on Internet but we thought that a new one only dedicaded to Joomla 4 would be good news for Joomla, its ecosystem and all the volunteers.
At templatejoomla.com, we don't fear competitors and we strongly believe in complementarity. The more there are projects like this online, the more it will be a sign of a dynamic ecosystem and a living CMS.
Of course, you may have a different opinion.
Moreover, many people wanted an official Joomla Templates Directory but it has never happened. This site is a modest answer to this request because it's a purely side personal project and it's not endorsed by OSM.
But there are others reasons, such as:
- there are tons of Joomla 3 websites to migrate to Joomla 4 and some of them will need to change their template.
Migration is always a tricky time for site owners and some of them could get tempted to switch to another platform if they dont find the perfect template for their J4 website. This site was mainly built for all these projects.
- to highlight the incredible and endless creativity of the Joomla templaters listed here.
Only one year after the release of J4, there are already 1700+ (and counting) Free and Premium original and powerful Joomla templates. Joomla templaters, you demonstrate that you are the best in the game. Kudos guys!
- because Joomla 4 is a fantastic major version and we must be proud and loud about it.
We strongly believe that this great version will bring new users to Joomla. We've built templateJoomla.com to offer a great showcase to J4 and to help these newcomers to find the best template for their projects.
- to support the Joomla ecosystem because we all need each other.
Developers need site builders who need the Community, etc. We are all on the same side, with the same passion for Joomla. Everyone of us can do a lot for Joomla, it's just a matter of time and willingness. Like the humminbird, we do our duty for Joomla at templateJoomla.com :)
Do you plan to display the Core Vitals Web scores of each templates?
No mainly for a good and logical reason.
To display the Core Vitals Web scores for a template, you need to install the template on a server and test it accordingly. And if you want relevant and valids scores, you must test every template on the same server. If you test the template displayed on the developer's server or on a marketplace, the scores won't be relevant because all the servers don't have the same configuration.
Displaying informations is great for end users, as long these informations are valids, relevant and reels.
What are the requirements for a templater to be listed on templatejoomla.com?
Unless you've been banned from the Joomla Community, we accept all Joomla 4 templates form every templater. It can be frontend or backend template, as long it's for Joomla 4. So basically, we accept every templates from every templaters.
If you provide Joomla 4 templates not yet listed on templatejoomla.com, we'd love to hear from you ASAP.
If you know a templater who might be interested to be listed on the Joomla 4 Templates Directory, contact us, please.
Can you detail us the process you use to add a new template?
Sure, let's see in details how it goes.
First, we create a new article in the backend and we add the following informations:
- the article title: the name of the template
- the article content: the short description of the template
- the tags: version of the template (J4 and J3)
- the note: the name of the templater (only for filtering purpose in backend)
- the intro image: the screenshot of the template - this is the longer part of the process because we resize each image before load them in the site.
- the URL A: the URL to the template page
- the URL A text: the name of the template
- the pricing of the template
- the framework of the template
- the category
- the templater
- the publication date: we add here the latest known date of the template (creation or update). In some case, we've indicated the latest update date of the framework.
When we have all the informations, it takes only few minutes to add a new template in the directory.
How the templates filtering is managed?
For this, we use the magical free module JL Content Fields Filter from Joomline.
Concretely, the informations are entered in custom fields in the backend and the module allows the visitor to filter the articles in the frontend. The module works perfectly and is very easy to configure.
It's simple, it's free and it's perfect!
However, there is one point of improvement. Indeed, the ARIA of the labels generated by the module are not unique, which penalizes accessibility. I sent this information to Joomline team and we can hope for an update of their module.
What extensions have you installed on this site?
Because "light is right", we wanted to stick to the core as much as possible. So, the site is built with Joomla 4 + Cassiopeia.
We've only added the following extensions:
- JL Content Fileds Filter: filtering the templates
- AJAX Infinity: add the infinite scroll on the homepage
- JCH Optimize
- Akeeba Backup
- JSitemap Pro
- itcs Matomo
To summarize, there a only 5 modules and we've only added 20 lines of CSS. As you can see, you don't need to install many extensions to create a (great) website because Joomla is natively very powerful.
How the Joomla templates are ordered on frontend?
The homepage of the site is a basic Blog view menu item.
Very logically, we've decided to prioritize templaters who keep their products up to date. So, the recently created or updated Joomla 4 templates are displayed first.
What overrides have you created for the Joomla 4 Templates Directory?
Of course to stick to the core as much as possible and because Joomla is very powerful, we've created some overrides, as usual.
The firsts were about the template header. We wanted to make the header as slim and as simple as possible. Here are the overrides created with some explanations.
To display the site name and its tagline, we've used a mod_custom displayed in menu position:
<!-- Desktop Tablette -->
<div class="ps-5 ms-5 navbar-brand navbar-brand d-none d-md-block">
<a class="brand-logo text-decoration-none" href="/">
<span class="fw-bold" title="TemplateJoomla">TemplateJoomla</span>
</a>
<div class="site-description small fst-italic">Joomla Template Directory</div>
</div>
<!-- Mobile -->
<div class="ms-4 navbar-brand d-md-none">
<div class="ms-2">
<div>
<a class="fs-2 text-decoration-none" href="/">
<span class="fw-bold" title="web-eau.net">TemplateJoomla</span>
</a>
</div>
</div>
</div>
Then, the main menu is displayed with a mod_menu in the menu position.
The last module displays the texts above the filters, we use a mod_article_latest where the code is completly removed and replace by this one:
<?php
/**
* @package Joomla.Site
* @author web-eau.net - Joomla 4 Templates Directory
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @file /templates/cassiopeia/html/mod_articles_latest/header-homepage.php
*/
defined('_JEXEC') or die;
$model = JModelLegacy::getInstance('Articles', 'ContentModel', array( 'ignore_request' => true )); // add ignore_request
$params = JFactory::getApplication()->getParams();
$model->setState('params', $params);
$model->setState('filter.category_id', 2);
$num_articles = $model->getTotal();
?>
<div class="p-5 bleu bg-white text-center">
<h1 class="display-6 lh-base">You need a new template for your Joomla site?</h1>
<h2 class="display-6 lh-base pb-4">There are <span class="fw-bolder"><?php echo $num_articles; ?></span> Joomla 4 templates listed here for you!
<br /><span class="fs-4">Recently created or updated templates are displayed first</span>
</div>
Then, we've create the blog item override. Because an image worths 1000 words, here are the codes of these overrides:
<?php
/**
* @package Joomla.Site
* @subpackage com_content
* @author web-eau.net - Joomla 4 Templates Directory
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @file /templates/cassiopeia/html/com_content/category/blog_item.php
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\FileLayout;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\Component\Content\Administrator\Extension\ContentComponent;
use Joomla\Component\Content\Site\Helper\RouteHelper;
// Create a shortcut for params.
$params = $this->item->params;
$canEdit = $this->item->params->get('access-edit');
$info = $params->get('info_block_position', 2);
// Check if associations are implemented. If they are, define the parameter.
$assocParam = (Associations::isEnabled() && $params->get('show_associations'));
$currentDate = Factory::getDate()->format('d M Y H:i:s');
$isUnpublished = ($this->item->state == ContentComponent::CONDITION_UNPUBLISHED || $this->item->publish_up > $currentDate)
|| ($this->item->publish_down < $currentDate && $this->item->publish_down !== null);
?>
<!-- Intro image -->
<?php if($this->item->catid == 2){?>
<?php $images = json_decode($this->item->images);?>
<?php $urls = json_decode($this->item->urls, true);?>
<div class="w-100 text-center rounded-top item-image">
<a target="_blank" href="<?php echo $urls['urla'];?>" itemprop="url" title="<?php echo $urls['urlatext'];?> Joomla template">
<img class="img-fluid" src="<?php echo $images->image_intro;?>" itemprop="thumbnailUrl" width="100%" height="211" loading="lazy" alt="<?php echo $urls['urlatext'];?> Joomla template"/>
</a>
</div>
<?php }else{ echo LayoutHelper::render('joomla.content.intro_image', $this->item); }?>
<!-- Title + tags + hits + intro text -->
<div class="rounded-bottom item-content py-3 ps-3 bg-white">
<?php if ($isUnpublished) : ?>
<div class="system-unpublished">
<?php endif; ?>
<!-- title -->
<?php if($this->item->catid == 2){?>
<div class="d-flex flex-row">
<div class="">
<h3 class="fs-3" itemprop="name">
<a target="_blank" href="<?php echo $urls['urla'];?>" itemprop="url" title="<?php echo $urls['urlatext'];?>"><?php echo $urls['urlatext'];?></a>
</h3>
</div>
<!-- tags -->
<div class=" ps-1">
<?php echo LayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
</div>
</div>
<?php }else{ echo LayoutHelper::render('joomla.content.blog_style_default_item_title', $this->item); }?>
<?php if ($canEdit) : ?>
<?php #echo LayoutHelper::render('joomla.content.icons', array('params' => $params, 'item' => $this->item)); ?>
<?php endif; ?>
<?php // @todo Not that elegant would be nice to group the params ?>
<?php $useDefList = ($params->get('show_modify_date') || $params->get('show_publish_date') || $params->get('show_create_date')
|| $params->get('show_hits') || $params->get('show_category') || $params->get('show_parent_category') || $params->get('show_author') || $assocParam); ?>
<?php if ($useDefList && ($info == 0 || $info == 2)) : ?>
<?php #echo LayoutHelper::render('joomla.content.info_block', array('item' => $this->item, 'params' => $params, 'position' => 'above')); ?>
<?php endif; ?>
<?php if ($info == 0 && $params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
<?php #echo LayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
<?php endif; ?>
<?php if (!$params->get('show_intro')) : ?>
<?php // Content is generated by content plugin event "onContentAfterTitle" ?>
<?php echo $this->item->event->afterDisplayTitle; ?>
<?php endif; ?>
<?php // Content is generated by content plugin event "onContentBeforeDisplay" ?>
<?php echo $this->item->event->beforeDisplayContent; ?>
<!-- Introtext -->
<div class="small pb-3 pe-5"><?php echo $this->item->introtext; ?> </div>
<?php if ($info == 1 || $info == 2) : ?>
<?php if ($useDefList) : ?>
<?php echo LayoutHelper::render('joomla.content.info_block', array('item' => $this->item, 'params' => $params, 'position' => 'below')); ?>
<?php endif; ?>
<?php if ($params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
<?php #echo LayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
<?php endif; ?>
<?php endif; ?>
<?php if ($params->get('show_readmore') && $this->item->readmore) :
if ($params->get('access-view')) :
$link = Route::_(RouteHelper::getArticleRoute($this->item->slug, $this->item->catid, $this->item->language));
else :
$menu = Factory::getApplication()->getMenu();
$active = $menu->getActive();
$itemId = $active->id;
$link = new Uri(Route::_('index.php?option=com_users&view=login&Itemid=' . $itemId, false));
$link->setVar('return', base64_encode(RouteHelper::getArticleRoute($this->item->slug, $this->item->catid, $this->item->language)));
endif; ?>
<?php echo LayoutHelper::render('joomla.content.readmore', array('item' => $this->item, 'params' => $params, 'link' => $link)); ?>
<?php endif; ?>
<?php if ($isUnpublished) : ?>
</div>
<?php endif; ?>
<?php // Content is generated by content plugin event "onContentAfterDisplay" ?>
<?php echo $this->item->event->afterDisplayContent; ?>
</div>
<?php
/**
* @package Joomla.Site
* @subpackage com_content
* @author web-eau.net - Joomla 4 Templates Directory
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @file /templates/cassiopeia/html/com_content/category/blog.php
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\FileLayout;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\Component\Content\Administrator\Extension\ContentComponent;
use Joomla\Component\Content\Site\Helper\RouteHelper;
use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
$app = Factory::getApplication();
$this->category->text = $this->category->description;
$app->triggerEvent('onContentPrepare', array($this->category->extension . '.categories', &$this->category, &$this->params, 0));
$this->category->description = $this->category->text;
$results = $app->triggerEvent('onContentAfterTitle', array($this->category->extension . '.categories', &$this->category, &$this->params, 0));
$afterDisplayTitle = trim(implode("\n", $results));
$results = $app->triggerEvent('onContentBeforeDisplay', array($this->category->extension . '.categories', &$this->category, &$this->params, 0));
$beforeDisplayContent = trim(implode("\n", $results));
$results = $app->triggerEvent('onContentAfterDisplay', array($this->category->extension . '.categories', &$this->category, &$this->params, 0));
$afterDisplayContent = trim(implode("\n", $results));
$htag = $this->params->get('show_page_heading') ? 'h2' : 'h1';
?>
<div class="com-content-category-blog blog" itemscope itemtype="https://schema.org/Blog">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header text-center">
<h1 class="text-center display-6 bleu lh-base py-5"> <?php echo $this->escape($this->params->get('page_heading')); ?> </h1>
</div>
<?php endif; ?>
<?php if ($this->params->get('show_category_title', 1)) : ?>
<<?php echo $htag; ?>>
<?php echo $this->category->title; ?>
</<?php echo $htag; ?>>
<?php endif; ?>
<?php echo $afterDisplayTitle; ?>
<?php if ($this->params->get('show_cat_tags', 1) && !empty($this->category->tags->itemTags)) : ?>
<?php $this->category->tagLayout = new FileLayout('joomla.content.tags'); ?>
<?php echo $this->category->tagLayout->render($this->category->tags->itemTags); ?>
<?php endif; ?>
<?php if ($beforeDisplayContent || $afterDisplayContent || $this->params->get('show_description', 1) || $this->params->def('show_description_image', 1)) : ?>
<div class="category-desc clearfix">
<?php if ($this->params->get('show_description_image') && $this->category->getParams()->get('image')) : ?>
<?php echo LayoutHelper::render(
'joomla.html.image',
[
'src' => $this->category->getParams()->get('image'),
'alt' => empty($this->category->getParams()->get('image_alt')) && empty($this->category->getParams()->get('image_alt_empty')) ? false : $this->category->getParams()->get('image_alt'),
]
); ?>
<?php endif; ?>
<?php echo $beforeDisplayContent; ?>
<?php if ($this->params->get('show_description') && $this->category->description) : ?>
<?php echo HTMLHelper::_('content.prepare', $this->category->description, '', 'com_content.category'); ?>
<?php endif; ?>
<?php echo $afterDisplayContent; ?>
</div>
<?php endif; ?>
<?php if (empty($this->lead_items) && empty($this->link_items) && empty($this->intro_items)) : ?>
<?php if ($this->params->get('show_no_articles', 1)) : ?>
<div class="alert alert-info">
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
<?php echo Text::_('COM_CONTENT_NO_ARTICLES'); ?>
</div>
<?php endif; ?>
<?php endif; ?>
<?php $leadingcount = 0; ?>
<?php if (!empty($this->lead_items)) : ?>
<div class="com-content-category-blog__items blog-items items-leading <?php echo $this->params->get('blog_class_leading'); ?>">
<?php foreach ($this->lead_items as &$item) : ?>
<div class="com-content-category-blog__item blog-item" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
<?php
$this->item = &$item;
echo $this->loadTemplate('item');
?>
</div>
<?php $leadingcount++; ?>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php
$introcount = count($this->intro_items);
$counter = 0;
?>
<?php if (!empty($this->intro_items)) : ?>
<?php $blogClass = $this->params->get('blog_class', ''); ?>
<?php if ((int) $this->params->get('num_columns') > 1) : ?>
<?php $blogClass .= (int) $this->params->get('multi_column_order', 0) === 0 ? ' masonry-' : ' columns-'; ?>
<?php $blogClass .= (int) $this->params->get('num_columns'); ?>
<?php endif; ?>
<div class="com-content-category-blog__items blog-items <?php echo $blogClass; ?>">
<?php foreach ($this->intro_items as $key => &$item) : ?>
<div class="shadow com-content-category-blog__item blog-item mb-4 bg-white"
itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
<?php
$this->item = & $item;
echo $this->loadTemplate('item');
?>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if (!empty($this->link_items)) : ?>
<div class="items-more">
<?php echo $this->loadTemplate('links'); ?>
</div>
<?php endif; ?>
<?php if ($this->maxLevel != 0 && !empty($this->children[$this->category->id])) : ?>
<div class="com-content-category-blog__children cat-children">
<?php if ($this->params->get('show_category_heading_title_text', 1) == 1) : ?>
<h3> <?php echo Text::_('JGLOBAL_SUBCATEGORIES'); ?> </h3>
<?php endif; ?>
<?php echo $this->loadTemplate('children'); ?> </div>
<?php endif; ?>
<?php if (($this->params->def('show_pagination', 1) == 1 || ($this->params->get('show_pagination') == 2)) && ($this->pagination->pagesTotal > 1)) : ?>
<div class="com-content-category-blog__navigation mx-auto text-center w-100">
<?php if ($this->params->def('show_pagination_results', 1)) : ?>
<p class="com-content-category-blog__counter counter float-end pt-3 pe-2">
<?php echo $this->pagination->getPagesCounter(); ?>
</p>
<?php endif; ?>
<div class="com-content-category-blog__pagination mx-auto text-center">
<?php echo $this->pagination->getPagesLinks(); ?>
</div>
</div>
<?php endif; ?>
</div>
We've also lightly edited the frontend display of the module JL Content Fields Filter, as you can see here:
<?php
/**
* JL Content Fields Filter
*
* @version 2.0.0
* @author Joomline
* @copyright (C) 2017-2019 Arkadiy Sedelnikov, Joomline. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
$doc = JFactory::getDocument();
if ($params->get('enable_no_jq', 0)) {
JHtml::_('jquery.framework');
$doc->addScript(JUri::root().'modules/mod_jlcontentfieldsfilter/assets/javascript/jlcontentfilter.js', array('version' => 'auto'));
} else {
$doc->addScript(JUri::root().'modules/mod_jlcontentfieldsfilter/assets/javascript/nojq_jlcontentfilter.js', array('version' => 'auto'));
}
$doc->addScriptDeclaration('
JlContentFieldsFilter.init({
"autho_send" : '.$autho_send.',
"form_identifier" : "mod-finder-searchform-'.$module->id.'",
"ajax" : '.$ajax.',
"ajax_selector" : "'.$ajax_selector.'",
"ajax_loader" : "'.$ajax_loader.'",
"ajax_loader_width" : '.$ajax_loader_width.'
});
');
if ($params->get('enable_css', 1)) {
$doc->addStyleSheet(JUri::root().'modules/mod_jlcontentfieldsfilter/assets/css/jlcontentfilter.css', array('version' => 'auto'));
}
use Joomla\CMS\Factory; // necessary bc we use herafter Factory::getApplication() and Factory::getDocument()
$app = Factory::getApplication(); // JFactory is indeed deprecated in J!4
$view = $app->input->getCMD('view', ''); // "view" would output "article" or "category" for example
if ('category' !== $view) {return; }
?>
<!-- Version Desktop - tablettes -->
<div class="mx-auto w-75 px-5 d-sm-none d-md-block d-none d-sm-block pb-4 mt-3 mb-4 shadow rounded bleu-bg">
<form id="mod-finder-searchform-<?php echo $module->id; ?>" action="<?php echo $action; ?>" method="<?php echo $form_method; ?>" class="form-search">
<div class="row jlcontentfieldsfilter<?php echo $moduleclass_sfx; ?>">
<?php foreach($fields as $v) : ?>
<?php if($v):?>
<div class="col-md-3 jlmf-section">
<?php echo $v; ?>
</div>
<?php endif;?>
<?php endforeach; ?>
<?php if($enableOrdering) : ?>
<div class="jlmf-section">
<?php echo $orderingSelect; ?>
</div>
<?php endif; ?>
</div>
<?php if($option == 'com_tags'){ ?>
<input type="hidden" name="tag_category_id" value="<?php echo $catid; ?>">
<?php } ?>
<input type="hidden" name="jlcontentfieldsfilter[is_filter]" value="1">
</form>
</div>
<!-- Version mobile -->
<div class="mx-auto px-5 d-block d-sm-none pb-4 mt-3 mb-4 shadow rounded bleu-bg">
<form id="mod-finder-searchform-<?php echo $module->id; ?>" action="<?php echo $action; ?>" method="<?php echo $form_method; ?>" class="form-search">
<div class="row jlcontentfieldsfilter<?php echo $moduleclass_sfx; ?>">
<?php foreach($fields as $v) : ?>
<?php if($v):?>
<div class="col-md-3 jlmf-section">
<?php echo $v; ?>
</div>
<?php endif;?>
<?php endforeach; ?>
<?php if($enableOrdering) : ?>
<div class="jlmf-section">
<?php echo $orderingSelect; ?>
</div>
<?php endif; ?>
</div>
<?php if($option == 'com_tags'){ ?>
<input type="hidden" name="tag_category_id" value="<?php echo $catid; ?>">
<?php } ?>
<input type="hidden" name="jlcontentfieldsfilter[is_filter]" value="1">
</form>
</div>
Then, the module mod_footer is also overrided to display the Joomla disclamer:
<?php
/**
* @package Joomla.Site
* @subpackage mod_footer
* @author web-eau.net - Joomla 4 Templates Directory
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
?>
<!-- Copyright desktop -->
<div class="mod-footer mx-auto text-center px-5 d-sm-none d-md-block d-none d-sm-block">
<div class="pt-2 footer2"><?php echo $lineone; ?> - <?php echo Text::_('MOD_FOOTER_LINE2'); ?> - The Joomla name and logo are used under<br />a limited license granted by Open Source Matters in the United States and other countries. TemplateJoomla is not affiliated with or endorsed by the Joomla project or by Open Source Matters.</div>
</div>
<!-- Copyright mobile -->
<div class="d-block d-sm-none mod-footer">
<div class="pt-2 footer2 pe-5"><?php echo $lineone; ?></div>
</div>
Of course, you can copy and use all these codes on your site without limit or restriction. Enjoy!
Where can I download a copy of your site to replicate it?
Some Joomla fanatics already asked us to provide them a quickstart package of this site.
So and because there's no Copyright on these free resources, we're glad to share this package whom anyone who need it:
Your Joomla Templates project is very helpful, how can I support it?
Thanks a lot, we really appreciate if you want to support to this project.
Unlike other similar projects, we will keep templatejoomla.com alive as long as possible because consistancy is the key. Of course, it depends mainly on us but also on the entire Joomla Community. As said, we need each others. There are different ways to help templatejoomla.com for free:
- if you have websites to migrate to Joomla 4 for your clients, indicate them templatejoomla.com's link to help them to find inspiration.
- share the link around you, on social medias, on your forums, on your newsletters, everywhere it's possible.
- write articles about Joomla templates on your blog and add a link to templatejoomla.com would be a great and friendly idea.
- favor the purchase of Joomla 4 templates through this directory because templatejoomla.com contains some traces of affiliate. Don't worry, it's secure and 100% transparent to you and the site will receive a few bucks if you or your clients buy your Joomla 4 templates by coming to this site.
- invite templaters not yet listed on the directory to contact us so we can add their Joomla 4 templates.
- flag us any error / improvment / advice you may have about this Joomla 4 Templates Directory:
This email address is being protected from spambots. You need JavaScript enabled to view it.
- and because domain name and hosting aren't free services, we also accept donations (of course)!