CECAFA Kagame Cup will prepare Tusker for CAF Confederation Cup challenge, says Mette

Tusker FC tactician Julien Mette during a training session at the Kenyatta University Ground. (Photo: Tusker/X)

Listen to article

5 min listen
Audio reading is not supported on this browser.
Ready

Thanks for listening. Continue with a related story, or tap the speaker icon on the next page to listen.

Gor Mahia, Tusker handed tough Kagame Cup draws as Joe Waithira faces Singida Black Stars

Erick Kariuki

 · 

1 week agoRead nextOpens a fresh page.

The French tactician believes facing some of East and Central <a href="https://absafricatv.com/can-south-africa-become-africas-startup-capital/” title=”Can South Africa Become Africa's Startup Capital?”>Africa‘s strongest clubs will better prepare his players for the intensity they will encounter when continental competition begins in September.

Tusker FC head coach Julien Mette believes the upcoming CECAFA Kagame Cup will provide his side with the ideal platform to prepare for their long-awaited return to continental football as the Brewers gear up for the 2026/27 CAF Confederation Cup.
The regional championship, which will be held in Kigali, Rwanda, from July 24 to August 7, comes at a crucial stage of Tusker’s pre-season programme.
Having qualified for the CAF Confederation Cup by lifting the FKF Cup, the Brewers are set to make their first appearance in the competition since 1994 and return to continental football for the first time since featuring in the 2022/23 CAF Champions League.

More To Read

  • Gor Mahia, Tusker handed tough Kagame Cup draws as Joe Waithira faces Singida Black Stars
  • Junior Starlets eye group A glory in high stakes Tanzania showdown
  • Tusker edge Kenya Police to lift FKF Cup, secure CAF Confederation cup ticket
  • FKF Cup final glory and millions on the line as Police, Tusker clash in Kwale
  • Coach Julien Mette eyes FKF Cup final as Tusker’s chance for redemption
  • Junior Starlets set for CECAFA test as coach Mildred Cheche finalises squad

For Mette, the invitation to participate in the CECAFA Kagame Cup could not have come at a better time.
“We are preparing to go to CECAFA, which was not initially in our plans, but we have been invited. This is something very good for us, especially ahead of continental football,” Mette said.
Rather than viewing the tournament purely as an opportunity to chase silverware, the French tactician believes facing some of East and Central Africa’s strongest clubs will better prepare his players for the intensity they will encounter when continental competition begins in September.

Latest Stories

  • Comedian Akuku Danger: My struggle with sickle cell disease and why I chose vasectomy
  • Why many Kenyan homes still rely on mwarubaini steam during cold season
  • High Court nullifies Sh12 billion Ngong-Riruta Railway project over constitutional breaches
  • Court hears bid to stop Moses Wetang’ula, Amason Kingi from political activities

“We will go to the tournament to prepare and try to win, though that is not the real target. We will face strong competitors, hard workers and killers, which is something good for us. We will play at the Amahoro Stadium, which is a top facility, and the level of opponents will introduce us to the high level of Africa,” he added.
Tusker have been handed one of the toughest draws of the competition after being placed in Group C alongside Sudanese giants Al Hilal, Rwandan heavyweights Rayon Sports and Zanzibar champions KVZ FC.
The group carries extra significance for Mette, who previously coached Rayon Sports before moving to Kenya, adding another intriguing subplot to the Brewers’ campaign.
The tournament will feature 12 clubs divided into three groups of four, with only the three group winners and the best second-placed side progressing to the semi-finals. According to CECAFA Competitions Manager Yusuf Mossi, the format means there is virtually no room for error during the group stage, making every fixture decisive.
Tusker open their campaign against Al Hilal on July 26 before taking on Rayon Sports and KVZ in what promises to be one of the most competitive groups in the tournament.
Despite acknowledging the calibre of opposition awaiting his side, Mette believes all participating clubs are in similar circumstances as they integrate new players and build fitness during pre-season.
“We have probably the favourite of the tournament, Al Hilal, in the same group. But all teams are facing the same situation as us, with many changes, so it is probably useless to try to analyse the tactical game plan of our opponents. They will have players on trial as we will, but we just have to prepare to face very good players in terms of speed of play and mentality,” he explained.
Although Tusker will travel to Kigali with ambitions of progressing beyond the group stage, the coach insists expectations must be balanced against the reality that the squad has only just begun preparations for the new season.
“The expectation is to go out of the group and reach the semi-final, which will be very good. But because of the late start to our pre-season, we have to be realistic and go game by game. If we lose, there will not be drama. We just have to represent Tusker and Kenya with good football and a good image in terms of fair play and attitude. That’s the main target,” said Mette.
The Brewers are currently completing their opening week of pre-season training, with workloads expected to increase ahead of their departure for Rwanda.
The tournament will also feature defending champions Singida Black Stars of Tanzania, who defeated Al Hilal 2-1 in last year’s final in Dar es Salaam to win their maiden CECAFA Kagame Cup title, while APR FC finished third. For Tusker, however, the focus extends beyond regional honours.
Every match in Kigali represents another step in preparing for a return to the continental stage, where the club hopes to make a lasting impression when the CAF Confederation Cup gets underway later this year.

Other Topics To Read

Top Stories Today

  • Seven US aid workers quarantined at Nanyuki Ebola‑isolation facility
  • ‘Spare my children’: How sickle cell disease drove comedian Akuku Danger to vasectomy
  • High Court nullifies Sh12 billion Ngong-Riruta Railway project over constitutional breaches
  • Court hears bid to stop Moses Wetang’ula, Amason Kingi from political activities
  • Gachagua: DCP to field candidates in all 47 counties in 2027 election
  • Kenya’s HPV vaccine coverage climbs as WHO calls for urgent action on zero-dose children

`;
}

return “;
}

function commentActionsMarkup(comment, canComment) {
const likeLabel = comment.liked_by_me ? ‘Liked’ : ‘Like’;
const likeCount = Number(comment.like_count || 0) > 0
? “
: ”;

const likeButton = canComment && comment.status === ‘approved’
? “
: “;

const replyButton = canComment && comment.status === ‘approved’
? “
: ”;

return `

`;
}

function commentMarkup(comment, canComment, isReply = false) {
const pendingBadge = comment.status && comment.status !== ‘approved’
? “
: ”;

const edited = comment.is_edited
? “
: ”;

const repliesHtml = Array.isArray(comment.replies) && comment.replies.length
? `

`
: “;

return `

`;
}

function replyFormMarkup(commentId) {
return `

`;
}

function setNotice(widget, message, type = ‘info’) {
const notice = widget.querySelector(‘[data-role=”notice”]’);
if (!notice) return;

if (!message) {
notice.hidden = true;
notice.textContent = ”;
notice.classList.remove(‘is-error’);
return;
}

notice.hidden = false;
notice.textContent = message;
notice.classList.toggle(‘is-error’, type === ‘error’);
}

function setCount(widget, total) {
const count = widget.querySelector(‘[data-role=”count”]’);
if (!count) return;

const num = Number(total || 0);
count.textContent = num === 1 ? ‘1 comment’ : `${num} comments`;
}

function openReplyBox(widget, commentId) {
widget.querySelectorAll(‘[data-role=”reply-box”]’).forEach(box => {
box.hidden = true;
box.innerHTML = ”;
});

const targetItem = widget.querySelector(`.ev-comments__item[data-comment-id=”${commentId}”]`);
if (!targetItem) return;

const replyBox = targetItem.querySelector(‘[data-role=”reply-box”]’);
if (!replyBox) return;

replyBox.hidden = false;
replyBox.innerHTML = replyFormMarkup(commentId);

const textarea = replyBox.querySelector(‘textarea’);
if (textarea) textarea.focus();
}

function closeReplyBox(container) {
if (!container) return;
container.hidden = true;
container.innerHTML = ”;
}

async function initCommentsWidget(widget) {
const state = {
articleId: Number(widget.dataset.articleId),
loadUrl: widget.dataset.loadUrl,
storeUrl: widget.dataset.storeUrl,
commentsBaseUrl: widget.dataset.commentsBaseUrl,
canComment: widget.dataset.canComment === ‘1’,
page: 1,
perPage: 10,
sort: ‘newest’,
total: 0,
hasMore: false,
busy: false
};

const list = widget.querySelector(‘[data-role=”list”]’);
const loading = widget.querySelector(‘[data-role=”loading”]’);
const empty = widget.querySelector(‘[data-role=”empty”]’);
const loadMoreBtn = widget.querySelector(‘[data-role=”load-more”]’);
const sortSelect = widget.querySelector(‘[data-role=”sort”]’);
const composerForm = widget.querySelector(‘[data-role=”composer-form”]’);

async function loadComments(reset = true) {
if (state.busy) return;

state.busy = true;
setNotice(widget, ”);
loading.hidden = false;

if (reset) {
state.page = 1;
list.innerHTML = ”;
empty.hidden = true;
}

try {
const url = new URL(state.loadUrl, window.location.origin);
url.searchParams.set(‘page’, state.page);
url.searchParams.set(‘per_page’, state.perPage);
url.searchParams.set(‘sort’, state.sort);

const response = await requestJson(url.toString(), {
method: ‘GET’,
headers: {
‘Accept’: ‘application/json’,
‘X-Requested-With’: ‘XMLHttpRequest’
}
});

const items = Array.isArray(response.data) ? response.data : [];
const meta = response.meta || {};

state.total = Number(meta.total || 0);
state.hasMore = !!meta.has_more;

setCount(widget, state.total);

if (reset) {
list.innerHTML = ”;
}

if (!items.length && reset) {
empty.hidden = false;
} else {
empty.hidden = true;
list.insertAdjacentHTML(
‘beforeend’,
items.map(item => commentMarkup(item, state.canComment, false)).join(”)
);
}

loadMoreBtn.hidden = !state.hasMore;
} catch (error) {
if (!list.children.length) {
empty.hidden = false;
empty.textContent = ‘Unable to load comments right now.’;
}
setNotice(widget, error.message || ‘Unable to load comments.’, ‘error’);
} finally {
loading.hidden = true;
state.busy = false;
}
}

async function submitTopLevelComment(form) {
const textarea = form.querySelector(‘textarea[name=”content”]’);
const button = form.querySelector(‘[data-role=”submit-comment”]’);

if (!textarea) return;

const content = textarea.value.trim();
if (!content) return;

const originalText = button ? button.textContent : ”;

try {
if (button) {
button.disabled = true;
button.textContent = ‘Posting…’;
}

const response = await requestJson(state.storeUrl, {
method: ‘POST’,
headers: buildJsonHeaders(),
body: JSON.stringify({
article_id: state.articleId,
content: content,
source_url: window.location.href
})
});

textarea.value = ”;

if (response?.data) {
list.insertAdjacentHTML(
‘afterbegin’,
commentMarkup(response.data, state.canComment, false)
);
empty.hidden = true;

if ((response.data.status || ”) === ‘approved’) {
state.total += 1;
setCount(widget, state.total);
}
}

setNotice(widget, response.message || ‘Comment posted successfully.’);
} catch (error) {
setNotice(widget, error.message || ‘Unable to post comment.’, ‘error’);
} finally {
if (button) {
button.disabled = false;
button.textContent = originalText || ‘Post comment’;
}
}
}

async function submitReply(form) {
const commentId = Number(form.dataset.commentId || 0);
const textarea = form.querySelector(‘textarea[name=”content”]’);
const button = form.querySelector(‘.ev-comments__reply-submit’);

if (!commentId || !textarea) return;

const content = textarea.value.trim();
if (!content) return;

const originalText = button ? button.textContent : ”;

try {
if (button) {
button.disabled = true;
button.textContent = ‘Posting…’;
}

const response = await requestJson(`${state.commentsBaseUrl}/${commentId}/reply`, {
method: ‘POST’,
headers: buildJsonHeaders(),
body: JSON.stringify({
article_id: state.articleId,
content: content,
source_url: window.location.href
})
});

if (response?.data) {
const parentItem = widget.querySelector(`.ev-comments__item[data-comment-id=”${commentId}”]`);
if (parentItem) {
const repliesWrap = parentItem.querySelector(‘.ev-comments__replies’);
if (repliesWrap) {
repliesWrap.insertAdjacentHTML(
‘beforeend’,
commentMarkup(response.data, state.canComment, true)
);
}
}
}

closeReplyBox(form.closest(‘[data-role=”reply-box”]’));
setNotice(widget, response.message || ‘Reply posted successfully.’);
} catch (error) {
setNotice(widget, error.message || ‘Unable to post reply.’, ‘error’);
} finally {
if (button) {
button.disabled = false;
button.textContent = originalText || ‘Post reply’;
}
}
}

async function toggleLike(button) {
const commentId = Number(button.dataset.commentId || 0);
if (!commentId) return;

const originalHtml = button.innerHTML;

try {
button.disabled = true;
button.innerHTML = ‘Working…’;

const response = await requestJson(`${state.commentsBaseUrl}/${commentId}/like`, {
method: ‘POST’,
headers: buildJsonHeaders(),
body: JSON.stringify({})
});

const liked = !!response?.data?.liked;
const likeCount = Number(response?.data?.like_count || 0);

button.classList.toggle(‘is-liked’, liked);
button.innerHTML = `${liked ? ‘Liked’ : ‘Like’} ${likeCount > 0 ? “ : ”}`;
} catch (error) {
button.innerHTML = originalHtml;
setNotice(widget, error.message || ‘Unable to update like.’, ‘error’);
} finally {
button.disabled = false;
}
}

if (composerForm) {
composerForm.addEventListener(‘submit’, function (e) {
e.preventDefault();
submitTopLevelComment(composerForm);
});
}

if (sortSelect) {
sortSelect.addEventListener(‘change’, function () {
state.sort = this.value || ‘newest’;
loadComments(true);
});
}

if (loadMoreBtn) {
loadMoreBtn.addEventListener(‘click’, function () {
if (state.busy || !state.hasMore) return;
state.page += 1;
loadComments(false);
});
}

widget.addEventListener(‘click’, function (e) {
const likeBtn = e.target.closest(‘[data-action=”toggle-like”]’);
if (likeBtn) {
e.preventDefault();
toggleLike(likeBtn);
return;
}

const replyBtn = e.target.closest(‘[data-action=”toggle-reply”]’);
if (replyBtn) {
e.preventDefault();
openReplyBox(widget, Number(replyBtn.dataset.commentId || 0));
return;
}

const cancelReplyBtn = e.target.closest(‘[data-action=”cancel-reply”]’);
if (cancelReplyBtn) {
e.preventDefault();
closeReplyBox(cancelReplyBtn.closest(‘[data-role=”reply-box”]’));
}
});

widget.addEventListener(‘submit’, function (e) {
const replyForm = e.target.closest(‘.ev-comments__reply-form’);
if (replyForm) {
e.preventDefault();
submitReply(replyForm);
}
});

loadComments(true);
}

document.addEventListener(‘DOMContentLoaded’, function () {
document.querySelectorAll(‘.ev-comments’).forEach(initCommentsWidget);
});
})();

Trending

Seven US aid workers quarantined at Nanyuki Ebola‑isolation facilityNews
|Mary Wambui
|2 hours ago
DCP’s Kamau Ngotho wins Ol Kalou by-election with 35,440 votesNews
|Lucy Mumbi
|9 hours ago
Comedian Akuku Danger: My struggle with sickle cell disease and why I chose vasectomyNews
|Charity Kilei
|19 minutes ago
Live blog: Vote counting begins after polls close in hotly-contested Ol Kalou by-electionNews
|Eastleigh Voice Reporter
|22 hours ago
UDA concedes defeat, congratulates DCP’s Kamau Ngotho in Ol Kalou by-electionNews
|Lucy Mumbi
|10 hours ago
Morocco back Ouahbi until 2030 as Atlas Lions shift focus to home World CupNews
|Erick Kariuki
|1 hour ago
Gachagua alleges police shooting left one dead, 20 injured in Ol KalouNews
|Rachael Mutabasi
|3 hours ago
Sammy Waweru Kamau vows unity, equal service after win in Ol Kalou by‑electionPolitics
|Rachael Mutabasi
|4 hours ago
Djibouti Defence Minister Hassan Omar Mohamed dies while receiving treatment in FranceAfrica
|Bashir Mbuthia
|21 hours ago
Over 50 per cent of registered voters cast ballots in Ol Kalou by-election amid chaos – IEBCPolitics
|Lucy Mumbi
|21 hours ago

Share.
Leave A Reply

Exit mobile version