feat: replace Tailwind CDN with static CSS build (item 20)
Deploy / Build & Push (Prod) (push) Successful in 59s
Deploy / Deploy Staging (push) Successful in 51s
Deploy / Deploy Prod (push) Successful in 51s

Multi-stage Dockerfile builds ~22KB minified CSS from Tailwind
instead of loading ~300KB JS from CDN on every request.
This commit is contained in:
2026-05-04 23:09:07 -03:00
parent 7f51e23029
commit f00bd1055d
8 changed files with 64 additions and 135 deletions
+4
View File
@@ -1 +1,5 @@
.DS_Store
node_modules/
output.css
package.json
package-lock.json
+14 -1
View File
@@ -1,15 +1,28 @@
FROM node:20-alpine AS build
WORKDIR /build
COPY input.css tailwind.config.js ./
COPY *.html ./
RUN npx tailwindcss@3 -i input.css -o output.css --minify
FROM nginx:alpine
ARG APP_URL=https://app.batida.io
COPY --from=build /build/output.css /usr/share/nginx/html/output.css
COPY index.html /tmp/index.html
COPY index.pt-br.html /tmp/index.pt-br.html
COPY vs.html /tmp/vs.html
COPY vs.pt-br.html /tmp/vs.pt-br.html
RUN sed -i "s|{{APP_URL}}|${APP_URL}|g" /tmp/index.html && \
sed -i "s|{{APP_URL}}|${APP_URL}|g" /tmp/index.pt-br.html && \
sed -i "s|{{APP_URL}}|${APP_URL}|g" /tmp/vs.html && \
sed -i "s|{{APP_URL}}|${APP_URL}|g" /tmp/vs.pt-br.html && \
mkdir -p /usr/share/nginx/html/pt-br && \
mv /tmp/index.html /usr/share/nginx/html/index.html && \
mv /tmp/index.pt-br.html /usr/share/nginx/html/pt-br/index.html
mv /tmp/index.pt-br.html /usr/share/nginx/html/pt-br/index.html && \
mv /tmp/vs.html /usr/share/nginx/html/vs.html && \
mv /tmp/vs.pt-br.html /usr/share/nginx/html/pt-br/vs.html
COPY nginx.conf /etc/nginx/conf.d/default.conf
+1 -41
View File
@@ -29,47 +29,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<!-- Tailwind -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
'mono': ['JetBrains Mono', 'monospace'],
},
colors: {
'ember': {
50: '#FFF7ED',
100: '#FFEDD5',
200: '#FED7AA',
300: '#FDBA74',
400: '#FB923C',
500: '#F97316',
600: '#EA580C',
700: '#C2410C',
800: '#9A3412',
900: '#7C2D12',
},
'frost': {
50: '#ECFEFF',
100: '#CFFAFE',
200: '#A5F3FC',
300: '#67E8F9',
400: '#22D3EE',
500: '#06B6D4',
600: '#0891B2',
700: '#0E7490',
800: '#155E75',
900: '#164E63',
}
}
}
}
}
</script>
<link rel="stylesheet" href="/output.css">
<style>
/* ===== CSS VARIABLES PARA DARK/LIGHT ===== */
+1 -41
View File
@@ -29,47 +29,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<!-- Tailwind -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
'mono': ['JetBrains Mono', 'monospace'],
},
colors: {
'ember': {
50: '#FFF7ED',
100: '#FFEDD5',
200: '#FED7AA',
300: '#FDBA74',
400: '#FB923C',
500: '#F97316',
600: '#EA580C',
700: '#C2410C',
800: '#9A3412',
900: '#7C2D12',
},
'frost': {
50: '#ECFEFF',
100: '#CFFAFE',
200: '#A5F3FC',
300: '#67E8F9',
400: '#22D3EE',
500: '#06B6D4',
600: '#0891B2',
700: '#0E7490',
800: '#155E75',
900: '#164E63',
}
}
}
}
}
</script>
<link rel="stylesheet" href="/output.css">
<style>
/* ===== CSS VARIABLES PARA DARK/LIGHT ===== */
+3
View File
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
+39
View File
@@ -0,0 +1,39 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./*.html'],
theme: {
extend: {
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
},
colors: {
ember: {
50: '#FFF7ED',
100: '#FFEDD5',
200: '#FED7AA',
300: '#FDBA74',
400: '#FB923C',
500: '#F97316',
600: '#EA580C',
700: '#C2410C',
800: '#9A3412',
900: '#7C2D12',
},
frost: {
50: '#ECFEFF',
100: '#CFFAFE',
200: '#A5F3FC',
300: '#67E8F9',
400: '#22D3EE',
500: '#06B6D4',
600: '#0891B2',
700: '#0E7490',
800: '#155E75',
900: '#164E63',
},
},
},
},
plugins: [],
};
+1 -26
View File
@@ -23,32 +23,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
'mono': ['JetBrains Mono', 'monospace'],
},
colors: {
'ember': {
50: '#FFF7ED', 100: '#FFEDD5', 200: '#FED7AA', 300: '#FDBA74',
400: '#FB923C', 500: '#F97316', 600: '#EA580C', 700: '#C2410C',
800: '#9A3412', 900: '#7C2D12',
},
'frost': {
50: '#ECFEFF', 100: '#CFFAFE', 200: '#A5F3FC', 300: '#67E8F9',
400: '#22D3EE', 500: '#06B6D4', 600: '#0891B2', 700: '#0E7490',
800: '#155E75', 900: '#164E63',
}
}
}
}
}
</script>
<link rel="stylesheet" href="/output.css">
<style>
:root, [data-theme="dark"] {
+1 -26
View File
@@ -23,32 +23,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
'mono': ['JetBrains Mono', 'monospace'],
},
colors: {
'ember': {
50: '#FFF7ED', 100: '#FFEDD5', 200: '#FED7AA', 300: '#FDBA74',
400: '#FB923C', 500: '#F97316', 600: '#EA580C', 700: '#C2410C',
800: '#9A3412', 900: '#7C2D12',
},
'frost': {
50: '#ECFEFF', 100: '#CFFAFE', 200: '#A5F3FC', 300: '#67E8F9',
400: '#22D3EE', 500: '#06B6D4', 600: '#0891B2', 700: '#0E7490',
800: '#155E75', 900: '#164E63',
}
}
}
}
}
</script>
<link rel="stylesheet" href="/output.css">
<style>
:root, [data-theme="dark"] {