Skip to content
Open
4 changes: 2 additions & 2 deletions .github/workflows/lighthouse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ jobs:
run: |
PREVIEW_URL="https://deploy-preview-${{ github.event.pull_request.number }}--expressjscom-preview.netlify.app"
echo "PREVIEW_URL=$PREVIEW_URL" >> "$GITHUB_ENV"
MAX_RETRIES=12
MAX_RETRIES=10
DELAY=10

echo "Checking Netlify preview: $PREVIEW_URL"
for i in $(seq 1 $MAX_RETRIES); do
if curl -s --head --max-time 5 "$PREVIEW_URL" | grep "200 OK" > /dev/null; then
if curl -s -I "$PREVIEW_URL" | grep "HTTP/.* 200" > /dev/null; then
Copy link
Member Author

@ShubhamOulkar ShubhamOulkar Aug 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correcting header status string. Now lighthouse audit is not running because of wrong status checking.

echo "✅ Preview is live!"
echo "skip_lighthouse=false" >> "$GITHUB_ENV"
exit 0
Expand Down
6 changes: 0 additions & 6 deletions _includes/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@
<nav id="navbar" aria-label="primary">
<input id="q" placeholder="🔎 search">
<ul id="navmenu">
<li>
<a href="/" id="home-menu" {% if page.menu=='home' %} class="active" {% endif %}>
{{ site.data[page.lang].menu.home }}
</a>
</li>
<li id="getting-started-menu" class="submenu">
<a href="/{{ page.lang }}/starter/installing.html" {% if page.menu=='starter' %} class="active" {% endif%}>
{{ site.data[page.lang].menu.getting_started }}
Expand Down Expand Up @@ -252,6 +247,5 @@
<span id="icon-sun">{% include icons/sun.svg %}</span>
</button>
{% include language-picker.html %}
{% include language-picker-mobile.html %}
</div>
</header>
20 changes: 0 additions & 20 deletions _includes/language-picker-mobile.html

This file was deleted.

34 changes: 15 additions & 19 deletions _includes/language-picker.html
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
<div class="desktop-lang-switcher">
{% assign url_parts = page.url | split: '/' %}
{% assign url_remainder = url_parts | slice: 2, url_parts.size | join: '/' %}
{% assign current_lang = page.lang %}
<button class="lang-btn" type="button" aria-haspopup="menu" aria-label="Change language">
<span id="current-lang"></span>
</button>
<ul class="lang-list submenu-content" aria-labelledby="current-lang" >
{% for lang in site.data.languages %}
<li>
<a href="/{{ lang.code }}/{{ url_remainder }}">
{% if lang.code == current_lang %}
<button id="langBtn" class="lang-btn" type="button" aria-expanded="false" aria-haspopup="listbox" aria-label="Change language">
{% include icons/i18n.svg %}
</button>
<ul id="langList" class="lang-list" role="listbox">
{% for lang in site.data.languages %}
<li>
<a href="/{{ lang.code }}/{{ url_remainder }}">
{% if lang.code == current_lang %}
<strong>{{ lang.name }}</strong>
{% else %}
{% else %}
{{ lang.name }}
{% endif %}
</a>
</li>
{% endfor %}
</ul>
<div id="languageData" data-languages='{{ site.data.languages | jsonify }}' style="display:none;"></div>
</div>
{% endif %}
</a>
</li>
{% endfor %}
</ul>
</div>
102 changes: 26 additions & 76 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -802,54 +802,27 @@ button.lang-btn {
cursor: pointer;
color: var(--card-fg);
padding: 0.2rem;
font-size: inherit;
display: flex;
justify-content: center;
align-items: center;
gap: 1rem;

&::after {
content: "";
display: block;
width: 0.8em;
height: 0.5em;
background-color: var(--card-fg);
clip-path: polygon(100% 0%, 0 0%, 50% 100%);
cursor: pointer;
pointer-events: none;
transition: transform 0.2s ease-in-out;
}
width: fit-content;
aspect-ratio: 1;
}

div.desktop-lang-switcher {
position: relative;
> button.lang-btn {
&:is(:focus, :hover) {
& + ul {
display: block;
opacity: 1;
visibility: visible;
}
}
}
/* enable lang list tabbing on keyboard focus */
&:focus-within .lang-list {
display: block;
opacity: 1;
visibility: visible;
}

> ul.lang-list {
display: none;
opacity: 0;
position: absolute;
list-style: none;
visibility: hidden;
&:is(:hover, :focus) {
display: block;
opacity: 1;
visibility: visible;
}
left: -75px;
z-index: 100;
background-color: var(--card-bg);
border: 1px solid;
border-radius: 10px;
padding: 0px;
min-width: max-content;

li a {
display: block;
padding: 5px 20px 5px 20px;
Expand All @@ -859,11 +832,22 @@ div.desktop-lang-switcher {
background: var(--hover-bg);
}
}

> li:first-child > a {
border-start-start-radius: 10px;
border-start-end-radius: 10px;
}

> li:last-child > a {
border-end-start-radius: 10px;
border-end-end-radius: 10px;
}
}

/* rotate arrow */
&:is(:hover,:focus-within) button.lang-btn::after {
transform: rotate(180deg);
> ul.lang-list.open {
display: block;
opacity: 1;
visibility: visible;
}
}

Expand Down Expand Up @@ -953,9 +937,6 @@ div.desktop-lang-switcher {
text-decoration: none;
}

#language-picker-menu {
display: none;
}

/* TOC side menu */

Expand Down Expand Up @@ -1320,26 +1301,6 @@ h2 a {
display: flex;
gap: 8px;
}

#language-picker-menu #navmenu>li:first-child {
display: flex;
}

#language-picker-menu #navmenu {
max-height: 70vh;
overflow-y: auto;
scrollbar-width: thin;
text-align: center;
}

#language-picker-menu {
display: block;
position: absolute;
top: 0;
right: 0;
width: 100%;
z-index: 1000;
}
}

/* TOC responsive */
Expand Down Expand Up @@ -1448,10 +1409,6 @@ h2 a {
header {
position: absolute;
}

#mobile-menu {
display:none;
}
}

/* For image callouts in writing-middleware.md */
Expand Down Expand Up @@ -1589,9 +1546,6 @@ h2 a {
margin-right: 0;
padding-right: 10px;
}



#blog-doc .blog-details + p > img {
margin-bottom: 15px;
}
Expand Down Expand Up @@ -1661,18 +1615,14 @@ blockquote {
}

@media all and (max-width: 1110px) {
.desktop-lang-switcher {
display: none;
.algolia-autocomplete {
display: none !important;
}

#mobile-menu {
display: block;
}

.algolia-autocomplete {
display: none !important;
}

#navbar {
padding: 0;
top: 1px;
Expand Down
10 changes: 0 additions & 10 deletions js/app.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
const languageElement = document.getElementById('languageData');
const languagesData = languageElement ? JSON.parse(languageElement.dataset.languages) : [];
const langDisplay = document.getElementById('current-lang');
const i18nMsgBox = document.getElementById("i18n-notice-box");

// display current language in language picker component
if (langDisplay) {
const currentLanguage = window.location.pathname.split('/')[1];
const matchedLang = languagesData.find(lang => lang.code === currentLanguage);
langDisplay.textContent = matchedLang ? matchedLang.name : 'English';
}

// add/remove class 'scroll' on scroll by 5px
const scrollTarget = document.querySelector('.logo-container');
const scrollObserver = new IntersectionObserver(
Expand Down
73 changes: 30 additions & 43 deletions js/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,35 @@ for (const el of itemsMenu) {
}

// Mobile Menu and Language Picker

const langBtn = document.getElementById("langBtn");
const langList = document.getElementById("langList");
const linkItemsMenu = document.querySelectorAll(".submenu > a");
const languageItems = document.querySelectorAll("#language-picker-menu > #navbar > #navmenu > .submenu > a");
const languagePickerMenu = document.querySelector("#language-picker-menu > #navbar > #navmenu");
const menu = document.querySelector("#navmenu");
const overlay = document.querySelector("#overlay");
const navButton = document.querySelector("#nav-button");
const languagePickerButton = document.querySelector("#language-picker-button");

function closeLangList() {
langList.classList.remove("open");
langBtn.setAttribute("aria-expanded", false);
}

function toggleLangList() {
const isOpen = langList.classList.toggle("open");
langBtn.setAttribute("aria-expanded", isOpen);
}

// toggle on button click
langBtn.addEventListener("click", (e) => {
e.stopPropagation();
toggleLangList();
});

// close on outside click except for lang btn
document.body.addEventListener("click", (e) => {
if (!langList.contains(e.target)) {
closeLangList();
}
});

for (const el of linkItemsMenu) {
el.addEventListener("click", (e) => {
Expand All @@ -85,56 +105,23 @@ for (const el of linkItemsMenu) {
e.preventDefault();
}
});

}

for (const el of languageItems) {
el.addEventListener("click", (e) => {
const href = el.getAttribute("href");

if (href && href !== "#") {
languagePickerMenu?.classList.remove("opens");
overlay?.classList.remove("blurs");
document.body.classList.remove("no-scroll");

window.location.href = href;
}
});
}

navButton?.addEventListener("click", () => {
const isLanguageMenuOpen = languagePickerMenu?.classList.contains("opens");
if (isLanguageMenuOpen) {
languagePickerMenu?.classList.remove("opens");
menu?.classList.toggle("opens");
} else {
menu?.classList.toggle("opens");
overlay?.classList.toggle("blurs");
document.body.classList.toggle("no-scroll");
}
});

languagePickerButton?.addEventListener("click", () => {
const isMenuOpen = menu?.classList.contains("opens");
if (isMenuOpen) {
menu?.classList.remove("opens");
languagePickerMenu?.classList.toggle("opens");
} else {
languagePickerMenu?.classList.toggle("opens");
overlay?.classList.toggle("blurs");
document.body.classList.toggle("no-scroll");
}
menu?.classList.toggle("opens");
overlay?.classList.toggle("blurs");
document.body.classList.toggle("no-scroll");
});

overlay?.addEventListener("click", () => {
if (menu?.classList.contains("opens")) {
menu.classList.remove("opens");
}
if (languagePickerMenu?.classList.contains("opens")) {
languagePickerMenu.classList.remove("opens");
}
overlay.classList.remove("blurs");
document.body.classList.remove("no-scroll");
// TODO : write helper function
const isOpen = langList.classList.toggle("open");
langBtn.setAttribute("aria-expanded", isOpen);
});

document
Expand Down