From 4233c431028f5f655ea4a2f169833dda71846783 Mon Sep 17 00:00:00 2001 From: Dan Date: Sun, 4 Jan 2026 15:31:47 +0000 Subject: [PATCH] Starting blog post on stackoverflow And loads of supporting graph code --- GRAPHS.md | 262 +++++++++++++ assets/sass/pages/blog.scss | 5 +- assets/sass/pages/resources.scss | 6 +- assets/sass/partials/_graphs.scss | 174 +++++++++ assets/sass/style.scss | 1 + config.yml | 23 -- .../ai-coding-trend.csv | 86 +++++ .../ai-trend.csv | 86 +++++ .../the-downfall-of-stackoverflow/index.md | 80 ++++ .../stackoverflow_questions_after_2019.csv | 86 +++++ .../stackoverflow_questions_over_time.csv | 212 +++++++++++ content/resources/_index.md | 3 +- layouts/_default/baseof.html | 3 + layouts/partials/site-header.html | 16 +- layouts/resources/list.html | 9 +- layouts/shortcodes/graph.html | 350 ++++++++++++++++++ 16 files changed, 1352 insertions(+), 50 deletions(-) create mode 100644 GRAPHS.md create mode 100644 assets/sass/partials/_graphs.scss create mode 100644 content/blog/the-downfall-of-stackoverflow/ai-coding-trend.csv create mode 100644 content/blog/the-downfall-of-stackoverflow/ai-trend.csv create mode 100644 content/blog/the-downfall-of-stackoverflow/index.md create mode 100644 content/blog/the-downfall-of-stackoverflow/stackoverflow_questions_after_2019.csv create mode 100644 content/blog/the-downfall-of-stackoverflow/stackoverflow_questions_over_time.csv create mode 100644 layouts/shortcodes/graph.html diff --git a/GRAPHS.md b/GRAPHS.md new file mode 100644 index 0000000..b2dc1de --- /dev/null +++ b/GRAPHS.md @@ -0,0 +1,262 @@ +# Graph Shortcode Documentation + +This Hugo site includes a custom shortcode for creating terminal-styled graphs that match the hacker green aesthetic. + +## Features + +- **Server-side processing**: Data is processed when Hugo builds the site +- **Terminal styling**: Automatic green color scheme matching the site theme +- **Multiple chart types**: Line, bar, pie, doughnut, radar, and more +- **Responsive**: Adapts to different screen sizes +- **Customizable**: Override colors and styling as needed + +## Basic Usage + +The shortcode supports two modes: +1. **Inline JSON data** - Embed data directly in your markdown +2. **CSV file data** - Load data from a CSV file in your page bundle + +### CSV File Mode (Recommended) + +Place your CSV file in the same directory as your blog post's `index.md`: + +```markdown +{{< graph id="my-chart" type="line" title="My Data" height="500" csv="data.csv" labelColumn="Date" dataColumn="Value" dateFormat="2006-01" >}} +{{< /graph >}} +``` + +**CSV Parameters:** +- `csv` - Filename of the CSV in the page bundle (required for CSV mode) +- `labelColumn` - Column name for x-axis labels (default: "Month") +- `dataColumn` - Column name for y-axis data (default: "Questions") +- `dateFormat` - Go date format for parsing timestamps (default: "2006-01") +- `skipRows` - Number of rows to skip from the start (default: 0) +- `maxRows` - Maximum number of rows to display (default: 0 = all) + +**Example CSV file** (`data.csv`): +```csv +Date,Value +2024-01,100 +2024-02,150 +2024-03,175 +``` + +### Inline JSON Mode + +### Line Chart + +```markdown +{{< graph id="my-chart" type="line" title="My Data" height="400" >}} +{ + "labels": ["Jan", "Feb", "Mar", "Apr", "May"], + "datasets": [{ + "label": "Sales", + "data": [12, 19, 3, 5, 2] + }] +} +{{< /graph >}} +``` + +### Bar Chart + +```markdown +{{< graph id="bar-example" type="bar" title="Monthly Revenue" height="350" >}} +{ + "labels": ["Q1", "Q2", "Q3", "Q4"], + "datasets": [{ + "label": "Revenue ($k)", + "data": [65, 59, 80, 81] + }] +} +{{< /graph >}} +``` + +### Multiple Datasets + +```markdown +{{< graph id="multi-line" type="line" title="Comparison" height="400" >}} +{ + "labels": ["2020", "2021", "2022", "2023", "2024"], + "datasets": [ + { + "label": "Product A", + "data": [30, 45, 60, 70, 85] + }, + { + "label": "Product B", + "data": [20, 35, 55, 65, 75] + } + ] +} +{{< /graph >}} +``` + +### Pie Chart + +```markdown +{{< graph id="pie-chart" type="pie" title="Market Share" height="400" >}} +{ + "labels": ["Chrome", "Firefox", "Safari", "Edge"], + "datasets": [{ + "data": [65, 15, 12, 8] + }] +} +{{< /graph >}} +``` + +## Parameters + +### Common Parameters + +| Parameter | Required | Default | Description | +|-----------|----------|---------|-------------| +| `id` | No | Auto-generated | Unique identifier for the chart | +| `type` | No | `line` | Chart type: `line`, `bar`, `pie`, `doughnut`, `radar`, `polarArea` | +| `title` | No | Empty | Chart title displayed above the graph | +| `height` | No | `400` | Height of the chart container in pixels | + +### CSV Mode Parameters + +| Parameter | Required | Default | Description | +|-----------|----------|---------|-------------| +| `csv` | Yes (for CSV mode) | - | Filename of CSV in page bundle | +| `labelColumn` | No | `"Month"` | CSV column name for labels (x-axis) | +| `dataColumn` | No | `"Questions"` | CSV column name for data (y-axis) | +| `dateFormat` | No | `"2006-01"` | Go date format string for parsing dates | +| `skipRows` | No | `0` | Number of data rows to skip | +| `maxRows` | No | `0` | Max rows to display (0 = all) | + +## Data Format + +The shortcode expects JSON data in Chart.js format. The basic structure is: + +```json +{ + "labels": ["Label 1", "Label 2", "Label 3"], + "datasets": [{ + "label": "Dataset Name", + "data": [value1, value2, value3] + }] +} +``` + +### Advanced Data Options + +You can override the automatic styling by providing Chart.js dataset properties: + +```markdown +{{< graph id="custom-style" type="line" title="Custom Colors" >}} +{ + "labels": ["A", "B", "C"], + "datasets": [{ + "label": "Custom", + "data": [10, 20, 30], + "borderColor": "rgb(255, 99, 132)", + "backgroundColor": "rgba(255, 99, 132, 0.2)", + "borderWidth": 3 + }] +} +{{< /graph >}} +``` + +## Color Scheme + +The shortcode automatically applies terminal-style colors: + +- **Primary**: `rgb(173, 255, 47)` (greenyellow) +- **Secondary**: `rgb(0, 255, 0)` (green) +- **Tertiary**: `rgb(0, 200, 0)` (darker green) +- **Grid**: `rgba(0, 255, 0, 0.2)` +- **Background**: `rgba(0, 255, 0, 0.1)` + +Multiple datasets automatically cycle through these colors. + +## CSS Classes + +The graph container has the class `.graph-container` with the following variants: + +- `.graph-container.full-width` - Full width graph (extends to edges) +- `.graph-container.compact` - Smaller padding and title + +To use variants, wrap the shortcode in a div: + +```html +
+{{< graph ... >}} +... +{{< /graph >}} +
+``` + +## Examples + +### StackOverflow Decline + +```markdown +{{< graph id="stackoverflow" type="line" title="Stack Overflow Activity" height="400" >}} +{ + "labels": ["2018", "2019", "2020", "2021", "2022", "2023", "2024"], + "datasets": [{ + "label": "Questions (thousands/month)", + "data": [170, 180, 195, 175, 150, 120, 85], + "fill": true + }] +} +{{< /graph >}} +``` + +### Technology Adoption + +```markdown +{{< graph id="tech-adoption" type="bar" title="Framework Adoption (%)" height="350" >}} +{ + "labels": ["React", "Vue", "Angular", "Svelte"], + "datasets": [{ + "label": "2023", + "data": [67, 45, 42, 18] + }, { + "label": "2024", + "data": [71, 48, 38, 25] + }] +} +{{< /graph >}} +``` + +### Response Time Distribution + +```markdown +{{< graph id="response-times" type="doughnut" title="API Response Times" height="400" >}} +{ + "labels": ["< 100ms", "100-500ms", "500ms-1s", "> 1s"], + "datasets": [{ + "data": [45, 35, 15, 5] + }] +} +{{< /graph >}} +``` + +## Tips + +1. **Keep IDs unique**: Each chart on a page needs a unique ID +2. **Data validation**: The shortcode validates JSON at build time - invalid JSON will cause build errors +3. **Responsive**: Charts are responsive by default, but fixed heights work better for consistency +4. **Performance**: Charts are rendered client-side but data is embedded at build time +5. **Testing**: Set `draft: false` and run `hugo server -D` to preview graphs + +## Troubleshooting + +**Graph not showing?** +- Check browser console for JavaScript errors +- Verify Chart.js is loaded (should be in page ``) +- Ensure JSON data is valid +- Check that the ID is unique on the page + +**Styling issues?** +- Graphs inherit the terminal theme automatically +- Custom colors can be added per dataset +- Container styling can be modified in `assets/sass/partials/_graphs.scss` + +**Build errors?** +- Invalid JSON will cause Hugo build failures +- Check for unclosed braces or missing commas +- Ensure the shortcode tags are properly formatted diff --git a/assets/sass/pages/blog.scss b/assets/sass/pages/blog.scss index 249cbe9..4667a44 100644 --- a/assets/sass/pages/blog.scss +++ b/assets/sass/pages/blog.scss @@ -271,14 +271,12 @@ } } - .tag-filter-link { background: rgba(255, 153, 0, 0.2); border-color: rgba(255, 153, 0, 0.5); color: #ff9900; text-shadow: 0 0 5px rgba(255, 153, 0, 0.5); } - } // Post title @@ -555,7 +553,8 @@ background: linear-gradient(#000, #000) padding-box, linear-gradient(180deg, #0f0, #000) border-box; - filter: grayscale(100%) contrast(1.2) brightness(0.9) sepia(100%) hue-rotate(60deg) saturate(300%); + filter: grayscale(100%) contrast(1.2) brightness(0.9) sepia(100%) + hue-rotate(60deg) saturate(300%); transition: all 0.3s ease; &:hover { diff --git a/assets/sass/pages/resources.scss b/assets/sass/pages/resources.scss index 65c6a81..3735953 100644 --- a/assets/sass/pages/resources.scss +++ b/assets/sass/pages/resources.scss @@ -52,8 +52,10 @@ } .whiteboard-description { - color: #546e7a; - font-size: 1.1rem; + font-family: "Caveat", cursive; + font-size: 28px; + font-weight: bold; + color: #2c3e50; max-width: 600px; margin: 0 auto; } diff --git a/assets/sass/partials/_graphs.scss b/assets/sass/partials/_graphs.scss new file mode 100644 index 0000000..c241f52 --- /dev/null +++ b/assets/sass/partials/_graphs.scss @@ -0,0 +1,174 @@ +// Graph container styling to match terminal aesthetic +.graph-container { + margin: 2rem 0; + padding: 20px 20px 100px 20px; // Extra bottom padding for rotated x-axis labels + background: rgba(0, 255, 0, 0.05); + border: 2px solid rgba(0, 255, 0, 0.3); + border-radius: 8px; + position: relative; + box-shadow: + 0 0 20px rgba(0, 255, 0, 0.1), + inset 0 0 40px rgba(0, 255, 0, 0.05); + overflow: visible; // Prevent clipping of labels + + @include media-down(lg) { + padding: 15px 15px 120px 15px; + margin: 1.5rem 0; + } + + // Terminal-style border glow on hover + &:hover { + border-color: rgba(0, 255, 0, 0.5); + box-shadow: + 0 0 30px rgba(0, 255, 0, 0.2), + inset 0 0 40px rgba(0, 255, 0, 0.08); + } + + // Scanline effect overlay + &::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: repeating-linear-gradient( + 0deg, + rgba(0, 0, 0, 0.1) 0px, + rgba(0, 0, 0, 0.1) 1px, + transparent 1px, + transparent 3px + ); + pointer-events: none; + z-index: 1; + border-radius: 6px; + } + + // Graph title + .graph-title { + color: greenyellow; + font-family: monospace; + font-size: 1.3rem; + margin: 0 0 15px 0; + text-align: center; + text-shadow: 0 0 10px rgba(173, 255, 47, 0.5); + text-transform: uppercase; + letter-spacing: 2px; + position: relative; + z-index: 2; + + @include media-down(lg) { + font-size: 1.1rem; + margin-bottom: 10px; + } + + &::after { + content: ""; + display: block; + width: 60%; + height: 2px; + background: linear-gradient( + 90deg, + transparent, + rgba(0, 255, 0, 0.6), + transparent + ); + margin: 8px auto 0; + box-shadow: 0 0 10px rgba(0, 255, 0, 0.4); + } + } + + // Canvas element + canvas { + position: relative; + z-index: 2; + filter: drop-shadow(0 0 8px rgba(0, 255, 0, 0.3)); + } + + // CRT flicker effect (subtle) + @keyframes graph-flicker { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.98; + } + } + + animation: graph-flicker 3s ease-in-out infinite; +} + +// Special styling for graphs in blog posts +.blog-summary, +.blogs-content { + .graph-container { + // Ensure proper spacing in blog context + margin: 2.5rem 0; + + @include media-down(lg) { + margin: 1.5rem 0; + } + } +} + +// Full-width graph variant +.graph-container.full-width { + margin-left: -20px; + margin-right: -20px; + border-radius: 0; + + @include media-down(lg) { + margin-left: -15px; + margin-right: -15px; + } +} + +// Compact graph variant +.graph-container.compact { + padding: 15px; + + .graph-title { + font-size: 1.1rem; + margin-bottom: 10px; + } + + @include media-down(lg) { + padding: 10px; + + .graph-title { + font-size: 1rem; + } + } +} + +// Loading state +.graph-container.loading { + &::after { + content: "LOADING DATA..."; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: #0f0; + font-family: monospace; + font-size: 1.2rem; + text-shadow: 0 0 10px rgba(0, 255, 0, 0.8); + animation: pulse 1.5s ease-in-out infinite; + z-index: 3; + } + + canvas { + opacity: 0.3; + } +} + +@keyframes pulse { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} diff --git a/assets/sass/style.scss b/assets/sass/style.scss index 31ff094..56bb0e1 100644 --- a/assets/sass/style.scss +++ b/assets/sass/style.scss @@ -14,6 +14,7 @@ @import "partials/lcd-display"; @import "partials/window"; @import "partials/crt-tv"; +@import "partials/graphs"; @import "partials/content-screens"; diff --git a/config.yml b/config.yml index f9b9050..73ee525 100644 --- a/config.yml +++ b/config.yml @@ -42,29 +42,6 @@ params: limit: 10 keys: ["title", "permalink", "summary", "content"] -menu: - main: - - identifier: about - name: about - url: /about/ - weight: 5 - - identifier: gear - name: gear & edc - url: /gear/ - weight: 10 - - identifier: resources - name: resources - url: /resources/ - weight: 12 - - identifier: archives - name: archives - url: /archives/ - weight: 15 - - identifier: tags - name: tags - url: /tags/ - weight: 20 - markup: highlight: noClasses: false diff --git a/content/blog/the-downfall-of-stackoverflow/ai-coding-trend.csv b/content/blog/the-downfall-of-stackoverflow/ai-coding-trend.csv new file mode 100644 index 0000000..e993347 --- /dev/null +++ b/content/blog/the-downfall-of-stackoverflow/ai-coding-trend.csv @@ -0,0 +1,86 @@ +Month,ai coding: (Worldwide) +2019-01,1 +2019-02,1 +2019-03,1 +2019-04,1 +2019-05,1 +2019-06,1 +2019-07,1 +2019-08,1 +2019-09,1 +2019-10,1 +2019-11,1 +2019-12,1 +2020-01,1 +2020-02,1 +2020-03,1 +2020-04,1 +2020-05,1 +2020-06,1 +2020-07,1 +2020-08,1 +2020-09,1 +2020-10,1 +2020-11,1 +2020-12,1 +2021-01,1 +2021-02,1 +2021-03,1 +2021-04,1 +2021-05,1 +2021-06,1 +2021-07,1 +2021-08,1 +2021-09,1 +2021-10,1 +2021-11,1 +2021-12,1 +2022-01,1 +2022-02,1 +2022-03,1 +2022-04,1 +2022-05,1 +2022-06,1 +2022-07,1 +2022-08,1 +2022-09,1 +2022-10,1 +2022-11,1 +2022-12,3 +2023-01,4 +2023-02,5 +2023-03,5 +2023-04,6 +2023-05,7 +2023-06,7 +2023-07,7 +2023-08,7 +2023-09,7 +2023-10,7 +2023-11,8 +2023-12,8 +2024-01,9 +2024-02,10 +2024-03,14 +2024-04,12 +2024-05,11 +2024-06,11 +2024-07,10 +2024-08,11 +2024-09,14 +2024-10,16 +2024-11,18 +2024-12,19 +2025-01,21 +2025-02,27 +2025-03,31 +2025-04,32 +2025-05,36 +2025-06,53 +2025-07,58 +2025-08,100 +2025-09,89 +2025-10,82 +2025-11,92 +2025-12,82 +2026-01,41 diff --git a/content/blog/the-downfall-of-stackoverflow/ai-trend.csv b/content/blog/the-downfall-of-stackoverflow/ai-trend.csv new file mode 100644 index 0000000..a694ed2 --- /dev/null +++ b/content/blog/the-downfall-of-stackoverflow/ai-trend.csv @@ -0,0 +1,86 @@ +Month,ai: (Worldwide) +2019-01,5 +2019-02,5 +2019-03,5 +2019-04,5 +2019-05,5 +2019-06,5 +2019-07,5 +2019-08,5 +2019-09,5 +2019-10,5 +2019-11,5 +2019-12,5 +2020-01,5 +2020-02,5 +2020-03,5 +2020-04,6 +2020-05,6 +2020-06,5 +2020-07,5 +2020-08,5 +2020-09,5 +2020-10,5 +2020-11,5 +2020-12,5 +2021-01,5 +2021-02,5 +2021-03,6 +2021-04,6 +2021-05,6 +2021-06,6 +2021-07,5 +2021-08,6 +2021-09,6 +2021-10,6 +2021-11,6 +2021-12,6 +2022-01,7 +2022-02,7 +2022-03,7 +2022-04,7 +2022-05,7 +2022-06,7 +2022-07,7 +2022-08,7 +2022-09,8 +2022-10,8 +2022-11,8 +2022-12,12 +2023-01,12 +2023-02,15 +2023-03,16 +2023-04,21 +2023-05,28 +2023-06,27 +2023-07,26 +2023-08,26 +2023-09,25 +2023-10,29 +2023-11,30 +2023-12,30 +2024-01,32 +2024-02,33 +2024-03,36 +2024-04,34 +2024-05,36 +2024-06,34 +2024-07,34 +2024-08,39 +2024-09,39 +2024-10,42 +2024-11,43 +2024-12,43 +2025-01,47 +2025-02,51 +2025-03,54 +2025-04,55 +2025-05,52 +2025-06,57 +2025-07,62 +2025-08,73 +2025-09,100 +2025-10,92 +2025-11,90 +2025-12,80 +2026-01,66 diff --git a/content/blog/the-downfall-of-stackoverflow/index.md b/content/blog/the-downfall-of-stackoverflow/index.md new file mode 100644 index 0000000..20e4ae8 --- /dev/null +++ b/content/blog/the-downfall-of-stackoverflow/index.md @@ -0,0 +1,80 @@ +--- +title: "The Downfall of StackOverflow" +date: 2026-02-04T13:58:02Z +tags: + - analysis + - ai +draft: true +--- + +This post was inspired by a post on [Hacker News](https://news.ycombinator.com/item?id=46482345) that linked to this [StackOverflow data](https://data.stackexchange.com/stackoverflow/query/1926661#graph). + +My kneejerk reaction was that the rise in AI and its code analysis capabilities have caused the downfall of StackOverflow. We can see a peak after a gradual decline in early 2020 (COVID bedroom coders?) which then returns to a roughly normal level by 2021, before starting a stark decline into obscurity, very much accelerating at the end of 2022. + +{{< graph id="stackoverflow-trend" type="line" title="Stack Overflow Questions Over Time" height="500" csv="stackoverflow_questions_over_time.csv" labelColumn="Month" dataColumn="" dateFormat="2006-01" >}} +{{< /graph >}} + +## The rise and fall + +StackOverflow had a hell of a run. From just 4 questions monthly in July 2008 to over 207,000 in March 2014—that's six years of basically uninterrupted growth. It became _the_ place every developer went when they were stuck. + +Then around 2014-2015, it plateaued. About 170,000-190,000 questions per month, which held steady for a few years before starting to slip. By 2019 we're down to around 150,000 per month. Still solid, but the writing was on the wall. + +Then it properly falls off a cliff. January 2023: 97,209 questions. December 2023: 42,601. January 2026: 321. That's a 99.8% drop from the 2020 peak. Three hundred and twenty-one questions. In a month. + +## Is it AI? + +Looking at Google Trends[^1] for AI-related searches, there's a bit of a gap between when StackOverflow started dying and when AI actually took off. + +{{< graph id="ai-trends" type="line" title="AI Search Trends" height="500" + csv="ai-coding-trend.csv,ai-trend.csv" + labelColumn="Month" + dataColumns="ai coding: (Worldwide),ai: (Worldwide)" + datasetLabels="AI Coding,AI General" + dateFormat="2006-01" >}} +{{< /graph >}} + +Both general AI interest and AI coding searches were basically flat from 2019 through most of 2022. Then in December 2022 it spikes—that's ChatGPT launching[^2]. + +Zooming in on 2019 onwards makes it clearer: + +{{< graph id="ai-trends-vs-questions" type="line" title="AI Search Trends vs StackOverflow Questions" height="500" + csv="stackoverflow_questions_after_2019.csv,ai-coding-trend.csv,ai-trend.csv" + labelColumn="Month" + dataColumns="Questions,ai coding: (Worldwide),ai: (Worldwide)" + datasetLabels="StackOverflow Questions,AI Coding,AI General" + yAxisIDs="y,y1,y1" + dateFormat="2006-01" >}} +{{< /graph >}} + +## The timeline doesn't quite add up + +Here's the thing though: StackOverflow's accelerated decline starts in 2021, well before anyone gave a shit about AI coding. From January 2021 (140,009 questions) to December 2022 (96,767 questions), it lost 31% of its traffic while "AI coding" searches sat at baseline. + +The AI coding surge doesn't really kick off until early 2023, then explodes through 2025, peaking in August. But by then StackOverflow was already down to 5,885 questions per month. + +## So what's actually going on? + +The data suggests AI accelerated something that was already happening. A few things probably contributed: + +**The saturation effect**: By 2021, StackOverflow had 16+ years of answered questions. How many times can you ask "how do I parse JSON in Python" before every variation is covered? The "just Google it" response became the correct answer because everything _had_ been Googled already. + +**The pre-AI decline (2021-2022)**: 31% drop over 18 months while AI coding searches were dead flat. This points to other shifts—better documentation, clearer error messages, frameworks maturing and becoming less footgun-y. Developers were finding answers without needing to ask. + +**The AI acceleration (2023-2025)**: ChatGPT launches November 30, 2022. By March 2023, StackOverflow drops from 123,614 questions to 87,543. AI tools give you instant answers without needing to wade through ten variations of your question that are marked as duplicates and locked. + +**The collapse (2025-2026)**: By mid-2025, AI coding tools are just... everywhere. GitHub Copilot, ChatGPT, Claude, all of them baked into every IDE and workflow. The August 2025 peak in "AI coding" searches lines up with StackOverflow hitting 5,885 questions. That's a 96.8% decline from five years earlier. + +## The bottom line + +AI didn't kill StackOverflow, but it's definitely finishing the job. The platform was already bleeding out when ChatGPT showed up—content saturation, better tooling, the ecosystem maturing. But AI coding tools changed the game completely. Why search through old forum posts when you can just ask? + +The inverse relationship is stark: as AI coding interest hits its peak in 2025, StackOverflow craters. By January 2026 we're at 321 questions. That's about the same as August 2008, when it was brand new. + +Twelve years to build it. Five years to tear it down. And yeah, the last three were almost certainly AI finishing what was already started. + +--- + +[^1]: Google Trends data provides relative search interest rather than absolute numbers, which may not capture the full picture. + +[^2]: [ChatGPT Launch Announcement](https://openai.com/index/chatgpt/) diff --git a/content/blog/the-downfall-of-stackoverflow/stackoverflow_questions_after_2019.csv b/content/blog/the-downfall-of-stackoverflow/stackoverflow_questions_after_2019.csv new file mode 100644 index 0000000..8f7dc97 --- /dev/null +++ b/content/blog/the-downfall-of-stackoverflow/stackoverflow_questions_after_2019.csv @@ -0,0 +1,86 @@ +Month,Questions +"2019-01-01 00:00:00","149628" +"2019-02-01 00:00:00","146421" +"2019-03-01 00:00:00","161159" +"2019-04-01 00:00:00","153558" +"2019-05-01 00:00:00","151393" +"2019-06-01 00:00:00","135935" +"2019-07-01 00:00:00","151081" +"2019-08-01 00:00:00","137181" +"2019-09-01 00:00:00","136935" +"2019-10-01 00:00:00","152721" +"2019-11-01 00:00:00","148338" +"2019-12-01 00:00:00","132623" +"2020-01-01 00:00:00","146735" +"2020-02-01 00:00:00","145191" +"2020-03-01 00:00:00","156037" +"2020-04-01 00:00:00","183016" +"2020-05-01 00:00:00","186573" +"2020-06-01 00:00:00","172002" +"2020-07-01 00:00:00","166135" +"2020-08-01 00:00:00","148452" +"2020-09-01 00:00:00","141887" +"2020-10-01 00:00:00","141948" +"2020-11-01 00:00:00","135088" +"2020-12-01 00:00:00","134035" +"2021-01-01 00:00:00","140009" +"2021-02-01 00:00:00","131810" +"2021-03-01 00:00:00","148900" +"2021-04-01 00:00:00","136022" +"2021-05-01 00:00:00","133911" +"2021-06-01 00:00:00","129106" +"2021-07-01 00:00:00","124130" +"2021-08-01 00:00:00","122273" +"2021-09-01 00:00:00","119882" +"2021-10-01 00:00:00","119008" +"2021-11-01 00:00:00","119260" +"2021-12-01 00:00:00","112278" +"2022-01-01 00:00:00","119459" +"2022-02-01 00:00:00","114114" +"2022-03-01 00:00:00","123614" +"2022-04-01 00:00:00","114422" +"2022-05-01 00:00:00","116346" +"2022-06-01 00:00:00","111741" +"2022-07-01 00:00:00","111059" +"2022-08-01 00:00:00","113048" +"2022-09-01 00:00:00","103965" +"2022-10-01 00:00:00","106366" +"2022-11-01 00:00:00","109719" +"2022-12-01 00:00:00","96767" +"2023-01-01 00:00:00","97209" +"2023-02-01 00:00:00","85973" +"2023-03-01 00:00:00","87543" +"2023-04-01 00:00:00","68746" +"2023-05-01 00:00:00","66749" +"2023-06-01 00:00:00","63858" +"2023-07-01 00:00:00","62938" +"2023-08-01 00:00:00","60319" +"2023-09-01 00:00:00","53046" +"2023-10-01 00:00:00","52743" +"2023-11-01 00:00:00","50646" +"2023-12-01 00:00:00","42601" +"2024-01-01 00:00:00","47854" +"2024-02-01 00:00:00","46292" +"2024-03-01 00:00:00","45070" +"2024-04-01 00:00:00","42776" +"2024-05-01 00:00:00","40485" +"2024-06-01 00:00:00","32243" +"2024-07-01 00:00:00","31740" +"2024-08-01 00:00:00","28059" +"2024-09-01 00:00:00","24947" +"2024-10-01 00:00:00","23319" +"2024-11-01 00:00:00","20891" +"2024-12-01 00:00:00","18029" +"2025-01-01 00:00:00","22394" +"2025-02-01 00:00:00","19340" +"2025-03-01 00:00:00","18965" +"2025-04-01 00:00:00","14138" +"2025-05-01 00:00:00","11824" +"2025-06-01 00:00:00","9392" +"2025-07-01 00:00:00","7841" +"2025-08-01 00:00:00","5885" +"2025-09-01 00:00:00","6132" +"2025-10-01 00:00:00","5415" +"2025-11-01 00:00:00","4366" +"2025-12-01 00:00:00","3862" +"2026-01-01 00:00:00","321" \ No newline at end of file diff --git a/content/blog/the-downfall-of-stackoverflow/stackoverflow_questions_over_time.csv b/content/blog/the-downfall-of-stackoverflow/stackoverflow_questions_over_time.csv new file mode 100644 index 0000000..edfdc83 --- /dev/null +++ b/content/blog/the-downfall-of-stackoverflow/stackoverflow_questions_over_time.csv @@ -0,0 +1,212 @@ +Month,Questions +"2008-07-01 00:00:00","4" +"2008-08-01 00:00:00","3749" +"2008-09-01 00:00:00","14040" +"2008-10-01 00:00:00","14578" +"2008-11-01 00:00:00","12717" +"2008-12-01 00:00:00","12081" +"2009-01-01 00:00:00","15833" +"2009-02-01 00:00:00","17581" +"2009-03-01 00:00:00","20482" +"2009-04-01 00:00:00","21336" +"2009-05-01 00:00:00","25814" +"2009-06-01 00:00:00","28326" +"2009-07-01 00:00:00","32483" +"2009-08-01 00:00:00","32775" +"2009-09-01 00:00:00","33054" +"2009-10-01 00:00:00","36331" +"2009-11-01 00:00:00","38518" +"2009-12-01 00:00:00","37795" +"2010-01-01 00:00:00","44938" +"2010-02-01 00:00:00","44811" +"2010-03-01 00:00:00","52236" +"2010-04-01 00:00:00","50084" +"2010-05-01 00:00:00","51996" +"2010-06-01 00:00:00","55750" +"2010-07-01 00:00:00","60848" +"2010-08-01 00:00:00","63660" +"2010-09-01 00:00:00","61230" +"2010-10-01 00:00:00","63777" +"2010-11-01 00:00:00","69693" +"2010-12-01 00:00:00","69573" +"2011-01-01 00:00:00","79911" +"2011-02-01 00:00:00","82942" +"2011-03-01 00:00:00","100970" +"2011-04-01 00:00:00","95562" +"2011-05-01 00:00:00","100229" +"2011-06-01 00:00:00","99027" +"2011-07-01 00:00:00","100445" +"2011-08-01 00:00:00","106917" +"2011-09-01 00:00:00","101722" +"2011-10-01 00:00:00","101032" +"2011-11-01 00:00:00","108450" +"2011-12-01 00:00:00","103172" +"2012-01-01 00:00:00","115434" +"2012-02-01 00:00:00","123299" +"2012-03-01 00:00:00","133000" +"2012-04-01 00:00:00","128064" +"2012-05-01 00:00:00","133515" +"2012-06-01 00:00:00","130323" +"2012-07-01 00:00:00","141906" +"2012-08-01 00:00:00","141528" +"2012-09-01 00:00:00","132241" +"2012-10-01 00:00:00","150083" +"2012-11-01 00:00:00","148310" +"2012-12-01 00:00:00","135471" +"2013-01-01 00:00:00","157850" +"2013-02-01 00:00:00","153402" +"2013-03-01 00:00:00","173814" +"2013-04-01 00:00:00","171546" +"2013-05-01 00:00:00","166468" +"2013-06-01 00:00:00","158334" +"2013-07-01 00:00:00","176636" +"2013-08-01 00:00:00","170215" +"2013-09-01 00:00:00","165374" +"2013-10-01 00:00:00","184133" +"2013-11-01 00:00:00","176033" +"2013-12-01 00:00:00","165192" +"2014-01-01 00:00:00","188797" +"2014-02-01 00:00:00","187751" +"2014-03-01 00:00:00","207493" +"2014-04-01 00:00:00","194022" +"2014-05-01 00:00:00","176017" +"2014-06-01 00:00:00","162354" +"2014-07-01 00:00:00","177066" +"2014-08-01 00:00:00","163406" +"2014-09-01 00:00:00","165866" +"2014-10-01 00:00:00","172887" +"2014-11-01 00:00:00","166598" +"2014-12-01 00:00:00","155299" +"2015-01-01 00:00:00","165978" +"2015-02-01 00:00:00","168513" +"2015-03-01 00:00:00","189769" +"2015-04-01 00:00:00","189967" +"2015-05-01 00:00:00","185878" +"2015-06-01 00:00:00","187915" +"2015-07-01 00:00:00","195439" +"2015-08-01 00:00:00","181413" +"2015-09-01 00:00:00","177859" +"2015-10-01 00:00:00","186418" +"2015-11-01 00:00:00","178205" +"2015-12-01 00:00:00","172586" +"2016-01-01 00:00:00","181380" +"2016-02-01 00:00:00","188742" +"2016-03-01 00:00:00","201941" +"2016-04-01 00:00:00","197067" +"2016-05-01 00:00:00","189772" +"2016-06-01 00:00:00","184660" +"2016-07-01 00:00:00","176974" +"2016-08-01 00:00:00","181960" +"2016-09-01 00:00:00","171676" +"2016-10-01 00:00:00","175399" +"2016-11-01 00:00:00","175326" +"2016-12-01 00:00:00","162421" +"2017-01-01 00:00:00","176969" +"2017-02-01 00:00:00","175280" +"2017-03-01 00:00:00","201543" +"2017-04-01 00:00:00","178508" +"2017-05-01 00:00:00","186511" +"2017-06-01 00:00:00","178175" +"2017-07-01 00:00:00","179856" +"2017-08-01 00:00:00","177742" +"2017-09-01 00:00:00","162369" +"2017-10-01 00:00:00","170083" +"2017-11-01 00:00:00","169012" +"2017-12-01 00:00:00","145330" +"2018-01-01 00:00:00","160544" +"2018-02-01 00:00:00","153155" +"2018-03-01 00:00:00","173466" +"2018-04-01 00:00:00","162981" +"2018-05-01 00:00:00","168104" +"2018-06-01 00:00:00","154885" +"2018-07-01 00:00:00","160095" +"2018-08-01 00:00:00","158544" +"2018-09-01 00:00:00","144581" +"2018-10-01 00:00:00","160501" +"2018-11-01 00:00:00","149820" +"2018-12-01 00:00:00","132269" +"2019-01-01 00:00:00","149628" +"2019-02-01 00:00:00","146421" +"2019-03-01 00:00:00","161159" +"2019-04-01 00:00:00","153558" +"2019-05-01 00:00:00","151393" +"2019-06-01 00:00:00","135935" +"2019-07-01 00:00:00","151081" +"2019-08-01 00:00:00","137181" +"2019-09-01 00:00:00","136935" +"2019-10-01 00:00:00","152721" +"2019-11-01 00:00:00","148338" +"2019-12-01 00:00:00","132623" +"2020-01-01 00:00:00","146735" +"2020-02-01 00:00:00","145191" +"2020-03-01 00:00:00","156037" +"2020-04-01 00:00:00","183016" +"2020-05-01 00:00:00","186573" +"2020-06-01 00:00:00","172002" +"2020-07-01 00:00:00","166135" +"2020-08-01 00:00:00","148452" +"2020-09-01 00:00:00","141887" +"2020-10-01 00:00:00","141948" +"2020-11-01 00:00:00","135088" +"2020-12-01 00:00:00","134035" +"2021-01-01 00:00:00","140009" +"2021-02-01 00:00:00","131810" +"2021-03-01 00:00:00","148900" +"2021-04-01 00:00:00","136022" +"2021-05-01 00:00:00","133911" +"2021-06-01 00:00:00","129106" +"2021-07-01 00:00:00","124130" +"2021-08-01 00:00:00","122273" +"2021-09-01 00:00:00","119882" +"2021-10-01 00:00:00","119008" +"2021-11-01 00:00:00","119260" +"2021-12-01 00:00:00","112278" +"2022-01-01 00:00:00","119459" +"2022-02-01 00:00:00","114114" +"2022-03-01 00:00:00","123614" +"2022-04-01 00:00:00","114422" +"2022-05-01 00:00:00","116346" +"2022-06-01 00:00:00","111741" +"2022-07-01 00:00:00","111059" +"2022-08-01 00:00:00","113048" +"2022-09-01 00:00:00","103965" +"2022-10-01 00:00:00","106366" +"2022-11-01 00:00:00","109719" +"2022-12-01 00:00:00","96767" +"2023-01-01 00:00:00","97209" +"2023-02-01 00:00:00","85973" +"2023-03-01 00:00:00","87543" +"2023-04-01 00:00:00","68746" +"2023-05-01 00:00:00","66749" +"2023-06-01 00:00:00","63858" +"2023-07-01 00:00:00","62938" +"2023-08-01 00:00:00","60319" +"2023-09-01 00:00:00","53046" +"2023-10-01 00:00:00","52743" +"2023-11-01 00:00:00","50646" +"2023-12-01 00:00:00","42601" +"2024-01-01 00:00:00","47854" +"2024-02-01 00:00:00","46292" +"2024-03-01 00:00:00","45070" +"2024-04-01 00:00:00","42776" +"2024-05-01 00:00:00","40485" +"2024-06-01 00:00:00","32243" +"2024-07-01 00:00:00","31740" +"2024-08-01 00:00:00","28059" +"2024-09-01 00:00:00","24947" +"2024-10-01 00:00:00","23319" +"2024-11-01 00:00:00","20891" +"2024-12-01 00:00:00","18029" +"2025-01-01 00:00:00","22394" +"2025-02-01 00:00:00","19340" +"2025-03-01 00:00:00","18965" +"2025-04-01 00:00:00","14138" +"2025-05-01 00:00:00","11824" +"2025-06-01 00:00:00","9392" +"2025-07-01 00:00:00","7841" +"2025-08-01 00:00:00","5885" +"2025-09-01 00:00:00","6132" +"2025-10-01 00:00:00","5415" +"2025-11-01 00:00:00","4366" +"2025-12-01 00:00:00","3862" +"2026-01-01 00:00:00","321" \ No newline at end of file diff --git a/content/resources/_index.md b/content/resources/_index.md index 192e39c..8a2654c 100644 --- a/content/resources/_index.md +++ b/content/resources/_index.md @@ -1,7 +1,8 @@ --- title: "Resources" -description: "A collection of useful tools, scripts, and experiments" draft: false --- +# Resources + Welcome to my whiteboard of resources. Here you'll find various tools, scripts, and experiments I've built and wanted to share. diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index d5fb00f..123dde1 100755 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -17,6 +17,9 @@ {{ end }} {{ block "favicon" . }} {{ partial "site-favicon.html" . }} {{ end }} + + + diff --git a/layouts/partials/site-header.html b/layouts/partials/site-header.html index e8b6cc4..72ff1f1 100755 --- a/layouts/partials/site-header.html +++ b/layouts/partials/site-header.html @@ -1,15 +1,3 @@
-
- {{ partial "site-navigation.html" . }} -
- - {{ with .Params.description }} -

- {{ . }} -

- {{ end }} -
-
-
\ No newline at end of file +
{{ partial "site-navigation.html" . }}
+ diff --git a/layouts/resources/list.html b/layouts/resources/list.html index 7b25983..dad3c37 100644 --- a/layouts/resources/list.html +++ b/layouts/resources/list.html @@ -3,16 +3,11 @@
-

{{ .Title }}

-
- {{ .Content }} -
+
{{ .Content }}
- {{ range .Pages }} - {{ .Render "summary" }} - {{ end }} + {{ range .Pages }} {{ .Render "summary" }} {{ end }}
diff --git a/layouts/shortcodes/graph.html b/layouts/shortcodes/graph.html new file mode 100644 index 0000000..f7a48e6 --- /dev/null +++ b/layouts/shortcodes/graph.html @@ -0,0 +1,350 @@ +{{- $id := .Get "id" | default (printf "chart-%d" now.UnixNano) -}} +{{- $type := .Get "type" | default "line" -}} +{{- $title := .Get "title" | default "" -}} +{{- $height := .Get "height" | default "400" -}} +{{- $csvFile := .Get "csv" -}} +{{- $labelCol := .Get "labelColumn" | default "Month" -}} +{{- $dataCol := .Get "dataColumn" | default "Questions" -}} +{{- $dataColumns := .Get "dataColumns" | default "" -}} +{{- $datasetLabels := .Get "datasetLabels" | default "" -}} +{{- $yAxisIDs := .Get "yAxisIDs" | default "" -}} +{{- $dateFormat := .Get "dateFormat" | default "2006-01" -}} +{{- $skipRows := .Get "skipRows" | default 0 | int -}} +{{- $maxRows := .Get "maxRows" | default 0 | int -}} + +{{- $chartData := dict -}} + +{{- if $csvFile -}} + {{/* CSV file mode - supports multiple CSV files */}} + {{- $csvFiles := strings.Split $csvFile "," -}} + {{- $dataColsList := slice -}} + {{- if ne $dataColumns "" -}} + {{- $dataColsList = strings.Split $dataColumns "," -}} + {{- end -}} + {{- $labelsList := slice -}} + {{- if ne $datasetLabels "" -}} + {{- $labelsList = strings.Split $datasetLabels "," -}} + {{- end -}} + {{- $yAxisList := slice -}} + {{- if ne $yAxisIDs "" -}} + {{- $yAxisList = strings.Split $yAxisIDs "," -}} + {{- end -}} + + {{- $labels := slice -}} + {{- $datasets := slice -}} + + {{/* Process each CSV file */}} + {{- range $fileIdx, $csvFileName := $csvFiles -}} + {{- $csvFileName = strings.TrimSpace $csvFileName -}} + {{- $csvResource := $.Page.Resources.GetMatch $csvFileName -}} + {{- if not $csvResource -}} + {{- errorf "CSV file '%s' not found in page bundle for %s. Make sure the file exists in the same directory as index.md" $csvFileName $.Page.File.Path -}} + {{- end -}} + + {{- $csvData := $csvResource | transform.Unmarshal -}} + {{- $data := slice -}} + + {{/* Determine which data column to use */}} + {{- $currentDataCol := $dataCol -}} + {{- if ge $fileIdx (len $dataColsList) -}} + {{- $currentDataCol = $dataCol -}} + {{- else -}} + {{- $currentDataCol = strings.TrimSpace (index $dataColsList $fileIdx) -}} + {{- end -}} + + {{/* Determine dataset label */}} + {{- $datasetLabel := $currentDataCol -}} + {{- if lt $fileIdx (len $labelsList) -}} + {{- $datasetLabel = strings.TrimSpace (index $labelsList $fileIdx) -}} + {{- end -}} + + {{/* Determine Y-axis ID */}} + {{- $yAxisID := "y" -}} + {{- if lt $fileIdx (len $yAxisList) -}} + {{- $yAxisID = strings.TrimSpace (index $yAxisList $fileIdx) -}} + {{- end -}} + + {{/* Process CSV rows */}} + {{- range $idx, $row := $csvData -}} + {{- if gt $idx $skipRows -}} + {{- if or (eq $maxRows 0) (le (len $data) $maxRows) -}} + {{/* Only set labels once from the first CSV file */}} + {{- if eq $fileIdx 0 -}} + {{/* Get label value */}} + {{- $labelRaw := "" -}} + {{- if reflect.IsMap $row -}} + {{- $labelRaw = index $row $labelCol -}} + {{- else -}} + {{/* Handle as slice/array - first column is label */}} + {{- $labelRaw = index $row 0 -}} + {{- end -}} + + {{- $label := $labelRaw -}} + + {{/* Try to parse and format date if it looks like a timestamp */}} + {{- $labelStr := printf "%v" $labelRaw -}} + {{- if strings.Contains $labelStr " 00:00:00" -}} + {{- $parsedTime := time.AsTime $labelStr -}} + {{- $label = $parsedTime.Format $dateFormat -}} + {{- end -}} + + {{- $labels = $labels | append $label -}} + {{- end -}} + + {{/* Get data value */}} + {{- $dataValue := 0 -}} + {{- if reflect.IsMap $row -}} + {{- $dataValue = index $row $currentDataCol | int -}} + {{- else -}} + {{/* Handle as slice/array - second column is data */}} + {{- $dataValue = index $row 1 | int -}} + {{- end -}} + + {{- $data = $data | append $dataValue -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{/* Add this dataset to the datasets array */}} + {{- $datasets = $datasets | append (dict "label" $datasetLabel "data" $data "yAxisID" $yAxisID) -}} + {{- end -}} + + {{- $chartData = dict "labels" $labels "datasets" $datasets -}} +{{- else -}} + {{/* JSON inline mode */}} + {{- if .Inner -}} + {{- $chartData = .Inner | transform.Unmarshal -}} + {{- else -}} + {{- errorf "Graph shortcode requires either CSV file or inline JSON data" -}} + {{- end -}} +{{- end -}} + +
+ {{- if $title -}} +

{{ $title }}

+ {{- end -}} + +
+ +