Skip to content

Commit a35d9f7

Browse files
committed
feat: added hashed css filesto address caching issues
1 parent f17c821 commit a35d9f7

File tree

9 files changed

+718
-62
lines changed

9 files changed

+718
-62
lines changed

_data/css-manifest.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"civichackdc.css": "civichackdc-cbf52d916e.css",
3+
"events.css": "events-fe4c9d527f.css",
4+
"styles.css": "styles-29eee3c87d.css"
5+
}

_includes/core/css.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,9 @@
55
rel="stylesheet"
66
/>
77

8-
<link rel="stylesheet" href="{{ '/assets/css/styles.css' | relative_url }}" />
8+
{% if site.data.css-manifest %}
9+
{% assign css_file = site.data.css-manifest["styles.css"] %}
10+
<link rel="stylesheet" href="{{ '/assets/css/' | append: css_file | relative_url }}" />
11+
{% else %}
12+
<link rel="stylesheet" href="{{ '/assets/css/styles.css' | relative_url }}" />
13+
{% endif %}

_layouts/base.html

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
<!doctype html>
22
<html lang="{{ page.lang | default: 'en-US' }}">
33
<head>
4-
{% include core/google-tag-manager-script.html %} {% include core/meta.html
5-
%} {% include core/css.html %} {% if page.page_css %}
6-
<link rel="stylesheet" href="{{ page.page_css | relative_url }}" />
4+
{% include core/google-tag-manager-script.html %}
5+
{% include core/meta.html%}
6+
{% include core/css.html %}
7+
{% if page.page_css %}
8+
{% assign css_filename = page.page_css | split: '/' | last %}
9+
{% if site.data.css-manifest[css_filename] %}
10+
{% assign hashed_css_file = site.data.css-manifest[css_filename] %}
11+
<link rel="stylesheet" href="{{ '/assets/css/' | append: hashed_css_file | relative_url }}" />
12+
{% else %}
13+
<link rel="stylesheet" href="{{ page.page_css | relative_url }}" />
14+
{% endif %}
715
{% endif %}
816
</head>
917

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
* { margin: 0; padding: 0; box-sizing: border-box; }
2+
body { font-family: 'Source Sans Pro Web', 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; line-height: 1.6; color: #333; }
3+
.container { max-width: 1200px; margin: 0 auto; padding: 0 20px; }
4+
5+
.hero { background: linear-gradient(0deg, #104377); color: white; padding: 4rem 0; text-align: center; }
6+
.hero h1 { font-size: 3.5rem; font-weight: bold; margin-bottom: 1rem; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); }
7+
.hero-banner { background: rgba(255,255,255,0.1); padding: 1rem 2rem; border-radius: 10px; margin: 2rem auto; max-width: 600px; backdrop-filter: blur(10px); }
8+
9+
.section { padding: 3rem 0; }
10+
.section.alt { background: #f8f9fa; }
11+
.section-title { text-align: center; font-size: 2.5rem; margin-bottom: 2rem; color: #333; }
12+
13+
.cta-buttons { display: flex; gap: 1rem; justify-content: center; margin-top: 2rem; }
14+
.btn { padding: 12px 30px; border: none; border-radius: 25px; font-weight: 600; text-decoration: none; display: inline-block; transition: all 0.3s; cursor: pointer; }
15+
.btn-secondary { background: #f8f9fa; color: #333; border: 2px solid #e9ecef; }
16+
.btn-secondary:hover { background: #104377; transform: translateY(-2px); }
17+
18+
.focus-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 1rem; margin: 2rem 0; }
19+
.focus-icon { background: white; padding: 1.5rem; border-radius: 12px; text-align: center; box-shadow: 0 4px 6px rgba(0,0,0,0.1); transition: transform 0.3s; }
20+
.focus-icon:hover { transform: translateY(-4px); }
21+
.focus-icon-symbol { width: 40px; height: 40px; background: #4A90E2; border-radius: 50%; margin: 0 auto 0.5rem; display: flex; align-items: center; justify-content: center; color: white; font-size: 1.2rem; }
22+
23+
.goals-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; }
24+
.goal-card { background: #f8f9fa; padding: 2rem; border-radius: 12px; border-left: 4px solid #4A90E2; transition: transform 0.3s, box-shadow 0.3s; }
25+
.goal-card:hover { transform: translateY(-4px); box-shadow: 0 8px 25px rgba(0,0,0,0.15); }
26+
.goal-number { background: #104377; color: white; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; margin-bottom: 1rem; }
27+
28+
.question-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; }
29+
.question-card { background: #f8f9fa; padding: 0.8rem; border-radius: 12px; border-left: 4px solid #4A90E2; transition: transform 0.3s, box-shadow 0.3s; }
30+
.question-card:hover { transform: translateY(-4px); box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); }
31+
32+
.partners-grid { display: flex; justify-content: center; flex-wrap: wrap; margin-top: 1rem; gap: 2rem; padding: 0; }
33+
.partner-logo { width: 120px; height: auto; object-fit: contain; }
34+
35+
.about-text p {
36+
margin-bottom: 1.5rem;
37+
}
38+
39+
@media (max-width: 768px) {
40+
.header-content { flex-direction: column; gap: 1rem; }
41+
nav ul { gap: 1rem; }
42+
.hero h1 { font-size: 2.5rem; }
43+
.focus-grid { grid-template-columns: repeat(2, 1fr); }
44+
.goals-grid { grid-template-columns: 1fr; }
45+
.cta-buttons { flex-direction: column; align-items: center; }
46+
}

assets/css/events-fe4c9d527f.css

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
.usa-card__media-text-wrapper {
2+
border: 3px solid #eec05e;
3+
width: 600px;
4+
box-sizing: border-box;
5+
padding: 10px;
6+
margin-bottom: 20px;
7+
transition: box-shadow 0.2s;
8+
}
9+
10+
.usa-card__media-text-wrapper:hover {
11+
box-shadow: 0 0 0 9px #eec05e33;
12+
}
13+
14+
.usa-card__link {
15+
display: block;
16+
text-decoration: none;
17+
color: inherit;
18+
}
19+
20+
.usa-card__img {
21+
width: 100%;
22+
height: auto;
23+
object-fit: cover;
24+
display: block;
25+
margin-bottom: 10px;
26+
}
27+
28+
.usa-card__body {
29+
padding: 0;
30+
}
31+
32+
.usa-card__heading {
33+
margin-top: 0;
34+
margin-bottom: 8px;
35+
}
36+
37+
.event-description {
38+
font-size: 16px;
39+
margin: 0 0 8px 0;
40+
}
41+
42+
/* New styles for past events grid */
43+
.past-events-grid {
44+
display: flex;
45+
flex-wrap: wrap;
46+
gap: 20px;
47+
list-style: none;
48+
padding-left: 0;
49+
}
50+
51+
.past-events-grid .usa-card__media-text-wrapper {
52+
width: auto;
53+
flex: 1 1 300px;
54+
max-width: 350px;
55+
}
56+
57+
.past-events-grid .usa-card__img {
58+
max-height: 200px;
59+
}

assets/css/styles-29eee3c87d.css

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gulpfile.js

Lines changed: 90 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
import gulp from "gulp";
2-
import imagemin, { gifsicle, svgo } from "gulp-imagemin";
2+
import imagemin, {gifsicle, svgo} from "gulp-imagemin";
33
import sharpResponsive from "gulp-sharp-responsive";
44
import uswds from "@uswds/compile";
5+
import rev from "gulp-rev";
6+
import revDelete from "gulp-rev-delete-original";
7+
58

69
/**
710
* USWDS version
811
*/
912

1013
uswds.settings.version = 3;
1114

15+
1216
/**
1317
* Configure USWDS source paths
1418
*/
1519
uswds.paths.src.projectSass = "./sass/custom";
20+
1621
// uswds.paths.src.theme = "./sass/theme";
1722

23+
1824
/**
1925
* Configure USWDS destination paths
2026
*/
@@ -24,6 +30,22 @@ uswds.paths.dist.js = "./assets/js";
2430
uswds.paths.dist.fonts = "./assets/fonts";
2531
uswds.paths.dist.img = "./assets/img";
2632

33+
34+
/**
35+
* CSS compilation with cache busting
36+
*/
37+
38+
39+
function addHashToCSS() {
40+
return gulp
41+
.src("./assets/css/{styles,events,civichackdc}.css") // Process multiple CSS files
42+
.pipe(rev()) // Add hash to filename
43+
.pipe(gulp.dest("./assets/css"))
44+
.pipe(rev.manifest('css-manifest.json')) // Create manifest
45+
.pipe(gulp.dest('./_data')); // Save manifest to Jekyll data folder
46+
}
47+
48+
2749
/**
2850
* Image processing tasks
2951
*/
@@ -32,68 +54,80 @@ const imageDest = "./assets/images";
3254

3355
// Resizes and optimizes raster images
3456
function resizeImages() {
35-
return gulp
36-
.src("_images/**/*.{jpg,jpeg,png}", { encoding: false })
37-
.pipe(
38-
sharpResponsive({
39-
formats: [
40-
// For each original format, create different sizes
41-
{
42-
width: 400,
43-
rename: { suffix: "-400w" },
44-
jpegOptions: { quality: 75, progressive: true },
45-
withoutEnlargement: true,
46-
},
47-
{
48-
width: 800,
49-
rename: { suffix: "-800w" },
50-
jpegOptions: { quality: 75, progressive: true },
51-
withoutEnlargement: true,
52-
},
53-
{
54-
width: 1200,
55-
rename: { suffix: "-1200w" },
56-
jpegOptions: { quality: 80, progressive: true },
57-
withoutEnlargement: true,
58-
},
59-
{
60-
width: 1800,
61-
rename: { suffix: "-1800w" },
62-
jpegOptions: { quality: 90, progressive: true },
63-
withoutEnlargement: true,
64-
},
65-
],
66-
})
67-
)
68-
.pipe(gulp.dest(imageDest));
57+
return gulp.src("_images/**/*.{jpg,jpeg,png}", {encoding: false}).pipe(sharpResponsive({
58+
formats: [
59+
60+
// For each original format, create different sizes
61+
{
62+
width: 400,
63+
rename: {
64+
suffix: "-400w"
65+
},
66+
jpegOptions: {
67+
quality: 75,
68+
progressive: true
69+
},
70+
withoutEnlargement: true
71+
}, {
72+
width: 800,
73+
rename: {
74+
suffix: "-800w"
75+
},
76+
jpegOptions: {
77+
quality: 75,
78+
progressive: true
79+
},
80+
withoutEnlargement: true
81+
}, {
82+
width: 1200,
83+
rename: {
84+
suffix: "-1200w"
85+
},
86+
jpegOptions: {
87+
quality: 80,
88+
progressive: true
89+
},
90+
withoutEnlargement: true
91+
}, {
92+
width: 1800,
93+
rename: {
94+
suffix: "-1800w"
95+
},
96+
jpegOptions: {
97+
quality: 90,
98+
progressive: true
99+
},
100+
withoutEnlargement: true
101+
}
102+
]
103+
})).pipe(gulp.dest(imageDest));
69104
}
70105

71106
// Optimizes vector images and GIFs
72107
function optimizeSvgsAndGifs() {
73-
return gulp
74-
.src("_images/**/*.{svg,gif}", { encoding: false })
75-
.pipe(
76-
imagemin(
77-
[
78-
gifsicle({ interlaced: true }),
79-
svgo({
80-
plugins: [
81-
{ name: "removeViewBox", active: false },
82-
{ name: "cleanupIDs", active: false },
83-
],
84-
}),
85-
],
86-
{ verbose: true }
87-
)
108+
return gulp.src("_images/**/*.{svg,gif}", {encoding: false}).pipe(imagemin([
109+
gifsicle(
110+
{interlaced: true}
111+
),
112+
svgo(
113+
{
114+
plugins: [
115+
{
116+
name: "removeViewBox",
117+
active: false
118+
}, {
119+
name: "cleanupIDs",
120+
active: false
121+
}
122+
]
123+
}
88124
)
89-
.pipe(gulp.dest(imageDest));
125+
], {verbose: true})).pipe(gulp.dest(imageDest));
90126
}
91127

92128
// Copies WebP files without processing
93129
function copyWebpFiles() {
94-
return gulp
95-
.src("_images/**/*.webp", { encoding: false })
96-
.pipe(gulp.dest(imageDest));
130+
return gulp.src("_images/**/*.webp", {encoding: false}).pipe(gulp.dest(imageDest));
97131
}
98132

99133
const processImages = gulp.parallel(resizeImages, optimizeSvgsAndGifs, copyWebpFiles);
@@ -102,11 +136,12 @@ function watchImages() {
102136
return gulp.watch(imageSource, processImages);
103137
}
104138

139+
105140
/**
106141
* Functions exported as gulp tasks
107142
*/
108143

109-
export const compile = gulp.series(processImages, uswds.compile);
144+
export const compile = gulp.series(processImages, uswds.compile, addHashToCSS);
110145
const watchUsdws = (done) => uswds.watch(done);
111146

112147
export const watch = gulp.parallel(watchUsdws, watchImages);

0 commit comments

Comments
 (0)