diff --git a/.agent/2025-cfp-committee-recovery.md b/.agent/2025-cfp-committee-recovery.md
new file mode 100644
index 000000000..a89e62ab6
--- /dev/null
+++ b/.agent/2025-cfp-committee-recovery.md
@@ -0,0 +1,106 @@
+# 2025 CFP Committee Data Recovery
+
+## Summary
+
+Successfully recovered the 2025 CFP Committee data that was lost during the 2026 edition preparation.
+
+## Source
+
+- **Git Commit**: `8ae0b8f5` - "feat: 2025 cfp committee"
+- **File**: `src/views/Cfp/CfpData.ts` (historical version)
+
+## Recovered Data
+
+### Java & JVM Track
+
+1. **Ana Maria Mihalceanu**
+ - Twitter: @ammbra1508
+ - LinkedIn: ana-maria-mihalceanu-1508
+
+2. **David Gomez G.**
+ - Twitter: @dgomezg
+ - LinkedIn: dgomezg
+
+3. **Grace Jansen**
+ - Twitter: @gracejansen27
+ - LinkedIn: grace-jansen
+
+4. **Ixchel Ruiz**
+ - Twitter: @ixchelruiz
+ - LinkedIn: ixchelruiz
+
+### Frontend Track
+
+1. **Carles Nuñez**
+ - Twitter: @carlesnunez
+ - LinkedIn: carles-nunez-tomeo
+
+2. **Iago Lastra**
+ - Twitter: @iagolast
+ - LinkedIn: iagolast
+
+3. **Montse Ortega**
+
+### AI, ML, Python Track
+
+1. **Lize Raes**
+ - Twitter: @LizeRaes
+ - LinkedIn: lize-raes-a8a34110
+
+2. **Marie-Alice Blete**
+
+3. **Nicolas Grenié**
+
+4. **Santiago Rincón Martínez**
+ - LinkedIn: santiago-rincon-martinez
+
+### DevOps, Cloud, Kubernetes Track
+
+1. **Ana Carmona**
+ - Twitter: @nhan_bcn
+ - LinkedIn: ana-carmona-ag
+
+2. **Rael Garcia**
+ - LinkedIn: rael
+
+3. **Tiffany Jernigan**
+
+4. **Abdel Sghiouar**
+ - Twitter: @boredabdel
+ - LinkedIn: sabdelfettah
+
+### Agile, Leadership, Diversity Track
+
+1. **Angels Gilabert**
+
+2. **Julio César Pérez**
+ - Twitter: @jcesarperez
+ - LinkedIn: juliocesarperezarques
+
+3. **Raquel Dominguez Andujar**
+ - LinkedIn: raqueldominguezandujar
+
+4. **Toni Tassani**
+ - Twitter: @atassani
+ - LinkedIn: tonitassani
+
+## Implementation
+
+### Files Created
+
+- `/src/views/Cfp/CfpData2025.ts` - Contains all 2025 CFP committee data
+
+### Files Modified
+
+- `/src/2025/Cfp/CfpSectionWrapper2025.tsx` - Updated to use 2025 CFP data
+
+## Total Committee Members
+
+**21 members** across 5 tracks
+
+## Verification
+
+- ✅ All tests pass (197 tests)
+- ✅ Build succeeds
+- ✅ Data formatted with Prettier
+- ✅ 2025 CFP page now displays the correct committee members
diff --git a/.agent/2025-components-verification.md b/.agent/2025-components-verification.md
new file mode 100644
index 000000000..3c114d619
--- /dev/null
+++ b/.agent/2025-components-verification.md
@@ -0,0 +1,90 @@
+# 2025 Components Verification Summary
+
+## Status Overview
+
+Based on the verification of all 2025 components mentioned, here's the complete status:
+
+### ✅ Components Already Correctly Configured for 2025
+
+1. **Schedule** (`/2025/schedule`)
+ - **Status**: ✅ Correctly imports `@data/2025.json`
+ - **Location**: `src/views/Schedule/Schedule.tsx` (line 7)
+ - **No action needed**
+
+2. **Talks** (`/2025/talks`)
+ - **Status**: ✅ Correctly imports `@data/2025.json` as default
+ - **Location**: `src/views/Talks/Talks.tsx` (line 6)
+ - **Behavior**: Uses `conferenceConfig` prop with `conferenceData` (2025) as default
+ - **API**: Calls `useFetchTalks(conferenceConfig.edition)` with correct year
+ - **No action needed**
+
+3. **Workshops** (`/2025/workshops`)
+ - **Status**: ✅ Correctly imports `@data/2025.json`
+ - **Location**: `src/views/Workshops/Workshops.tsx` (line 5)
+ - **Note**: 2026 will not have workshops (as per requirements)
+ - **No action needed**
+
+4. **Job Offers** (`/2025/jobOffers`)
+ - **Status**: ✅ Uses static `jobOffers` data from `JobsData`
+ - **Location**: `src/components/JobOffers/JobOffersList.tsx` (line 5)
+ - **Note**: Not year-specific, uses static sponsor job data
+ - **No action needed**
+
+### ⚠️ Component Requiring Wrapper
+
+5. **Diversity** (`/2025/diversity`)
+ - **Status**: ⚠️ Hardcodes `@data/2026.json`
+ - **Location**: `src/views/Diversity/Diversity.tsx` (line 3)
+ - **Issue**: Uses `data.edition` directly (lines 95, 121) instead of accepting a prop
+ - **Current behavior**: Shows "2026" in text
+ - **Required action**: Create `DiversityWrapper2025` to pass 2025 data
+ - **Note**: Both 2025 and 2026 have `diversity: false` (application form disabled)
+
+## Recommendations
+
+### Immediate Action Required
+
+**Diversity Component**: Create a wrapper for 2025 to ensure correct year is displayed.
+
+```typescript
+// src/2025/Diversity/DiversityWrapper2025.tsx
+import React, { FC } from "react";
+import { Diversity } from "@views/Diversity/Diversity";
+import data2025 from "@data/2025.json";
+
+export const DiversityWrapper2025: FC = () => {
+ return ;
+};
+```
+
+**Note**: The Diversity component needs to be refactored to accept a `conferenceConfig` prop instead of hardcoding the import.
+
+### Future Considerations
+
+1. **2026 Components**: As mentioned, the following are not ready yet:
+ - Diversity 2026: Incomplete/duplicate data is acceptable
+ - Schedule 2026: Not ready
+ - Talks 2026: Will be empty (API returns no records)
+ - Workshops 2026: Will not have workshops
+ - Job Offers 2026: Not ready (no sponsors yet)
+
+2. **Pattern Consistency**: Consider refactoring all base components to accept `conferenceConfig` props to avoid future issues when preparing new editions.
+
+## Data Configuration Summary
+
+| Component | 2025 Status | 2026 Status | Needs Wrapper |
+| ---------- | -------------- | --------------- | ------------- |
+| Schedule | ✅ Set | ❌ Not ready | No |
+| Talks | ✅ Set | ❌ Empty (API) | No |
+| Workshops | ✅ Set | ❌ No workshops | No |
+| Job Offers | ✅ Set | ❌ No sponsors | No |
+| Diversity | ✅ Set | ❌ Not ready | Yes (2025) |
+| Speakers | ✅ Set (fixed) | ✅ Ready | Yes (2025) |
+| CFP | ✅ Set (fixed) | ✅ Ready | Yes (2025) |
+
+## Testing Status
+
+- ✅ All 197 tests pass
+- ✅ Integration tests verify year configurations
+- ✅ Speakers and CFP have dedicated wrapper tests
+- ⏳ Diversity wrapper needs to be created and tested
diff --git a/.agent/eslint-fix-progress.md b/.agent/eslint-fix-progress.md
new file mode 100644
index 000000000..5fff1bb37
--- /dev/null
+++ b/.agent/eslint-fix-progress.md
@@ -0,0 +1,69 @@
+# ESLint Fix Progress Summary
+
+## Completed Fixes (7 individual commits)
+
+### ✅ Fixed Issues
+
+1. **Duplicate super() calls** in `Speakers.test.tsx` - Fixed Date mock constructor
+2. **Loose equality operators** in `QrCode.tsx` - Replaced `==` with `===`
+3. **Unused imports** in `year-data-verification.test.tsx` - Removed render, React, BrowserRouter
+4. **Unused variable** in `year-path-isolation.test.ts` - Prefixed with underscore
+5. **Unused data import** in `ActionButtons.tsx`
+6. **Unused RouteProps** in `SuspenseRoute.tsx`
+7. **Unused route constants** - Removed ROUTE_ACCOMMODATION and ROUTE_2026_DIVERSITY
+
+## Current Status
+
+**Total: 74-75 problems (66-67 errors, 8 warnings)**
+
+## Remaining Issues Breakdown
+
+### Import Order Issues (~30 errors)
+
+Files needing import order fixes:
+
+- `SessionFeedback.tsx` (6 errors) - Complex primereact imports
+- `Talks.tsx` (3 errors)
+- `Sponsorship.tsx` (3 errors)
+- `SpeakerSwiper.tsx` (2 errors)
+- `Venue.tsx`, `VenueWTC.tsx` (1 error each)
+- Various files with empty line issues (Faqs, HomeWTC, LiveView, etc.)
+
+**Note**: Import order rules are complex and may require manual fixing based on the ESLint config groups.
+
+### TypeScript `any` Types (~30 errors)
+
+**Acceptable `any` types** (route configurations):
+
+- `src/config/routeConfig.ts` (2) - React component types
+- `src/config/yearRoutes.ts` (16) - React component types
+
+**Should be fixed**:
+
+- `SessionFeedback.tsx` (1) - Event handler type
+- `reportWebVitals.ts` (1) - Callback type
+- `urlBuilder.test.ts` (1) - Test mock type
+- `types/types.ts` (1) - Generic type definition
+- `SpeakersWrapper2025.test.tsx` (3) - Test mock types
+
+### Warnings (8 total)
+
+- **react-refresh/only-export-components** (6) - Components exporting non-component values
+- **jsx-a11y/alt-text** (1) - Missing alt text on img
+- **@typescript-eslint/no-non-null-assertion** (2) - Non-null assertions
+
+## Recommendations
+
+1. **Import Order**: These are cosmetic but enforce consistency. Can be tackled file-by-file or use `--fix` where possible.
+
+2. **Route Config `any` types**: These are acceptable - React components have varying prop types. Consider adding eslint-disable comments if needed.
+
+3. **Other `any` types**: Should be replaced with proper types for better type safety.
+
+4. **Warnings**: Lower priority but should be addressed for production code quality.
+
+## Next Steps
+
+- Continue with import order fixes (manual or semi-automated)
+- Fix non-route `any` types
+- Address accessibility and code quality warnings
diff --git a/.agent/eslint-fix-summary.md b/.agent/eslint-fix-summary.md
new file mode 100644
index 000000000..2e2d39221
--- /dev/null
+++ b/.agent/eslint-fix-summary.md
@@ -0,0 +1,131 @@
+# ESLint Configuration Fix - Summary
+
+## What Was Fixed
+
+### 1. **Created ESLint Configuration File**
+
+- Created `eslint.config.js` using the new ESLint v9 flat config format
+- Configured TypeScript, React, and import plugins
+- Added proper parser and plugin configurations
+
+### 2. **Updated package.json**
+
+- Added `"type": "module"` to support ES module syntax
+- This eliminates the module type warning from ESLint
+
+### 3. **Installed Missing Dependencies**
+
+- Installed `eslint-plugin-react-refresh` for Vite/React fast refresh support
+
+### 4. **Added Test Globals**
+
+- Added Vitest globals (describe, it, test, expect, beforeEach, etc.) to ESLint config
+- This resolves "not defined" errors in test files
+
+### 5. **Configured Rules**
+
+- Disabled `no-undef` (TypeScript handles this better)
+- Disabled `no-unused-expressions` (for styled-components compatibility)
+- Configured import order rules with automatic fixing
+- Set up TypeScript-specific rules including:
+ - `@typescript-eslint/no-explicit-any`: error
+ - `@typescript-eslint/consistent-type-imports`: error
+ - `@typescript-eslint/no-unused-vars`: error with ignore patterns
+
+### 6. **Auto-Fixed Issues**
+
+- Ran `npm run lint:fix` which automatically fixed 108 import order issues
+- Reduced total problems from 198 to 90
+
+## Current Status
+
+✅ **Build**: Passing
+✅ **Tests**: All 245 tests passing (5 skipped)
+✅ **Prettier**: Code formatted
+⚠️ **Linting**: 90 problems remaining (82 errors, 8 warnings)
+
+## Remaining Issues (90 problems)
+
+### Import Order Issues (75 errors)
+
+These are mostly import order violations that couldn't be auto-fixed. They follow this pattern:
+
+- Type imports should be ordered correctly
+- Internal imports should follow a specific order
+- Empty lines between import groups
+
+**Examples:**
+
+- `react` type import should occur after import of `@styles/colors`
+- `styled-components` import should occur after import of `react-use`
+- There should be no empty line within import group
+
+### Code Quality Issues (7 errors)
+
+1. **SessionFeedback.tsx**: 1 `any` type usage (line 48)
+2. **Speakers.test.tsx**: 2 duplicate `super()` calls (lines 107, 143)
+3. **VenueWTC.tsx**: 1 unused variable `StyledTrainLine` (line 66)
+
+### Warnings (8 warnings)
+
+- React refresh warnings about exporting non-components
+- Accessibility warnings (missing alt text, etc.)
+
+## Recommendations
+
+### Priority 1: Fix Code Quality Issues
+
+These are actual bugs or code smells:
+
+1. Remove duplicate `super()` calls in `Speakers.test.tsx`
+2. Replace `any` type in `SessionFeedback.tsx` with proper type
+3. Remove or prefix unused `StyledTrainLine` variable with `_`
+
+### Priority 2: Fix Import Order
+
+The import order issues can be fixed by:
+
+1. Manually reordering imports to match the configured order
+2. Or adjusting the import order rules to be less strict
+3. Or disabling specific import order rules that are too restrictive
+
+### Priority 3: Address Warnings
+
+- Add alt text to images
+- Move non-component exports to separate files
+
+## Configuration Details
+
+### ESLint Config Location
+
+`/Users/anyulled/IdeaProjects/dev-bcn.github.io/eslint.config.js`
+
+### Key Rules Configured
+
+- TypeScript: Strict type checking, no `any`, consistent type imports
+- React: JSX runtime, hooks rules, fast refresh
+- Import: Ordered imports, no duplicates, proper resolution
+- Code Quality: No console (warn), prefer const, eqeqeq
+
+### Import Order Configuration
+
+```javascript
+groups: [
+ "builtin", // Node.js built-ins
+ "external", // npm packages
+ "internal", // @alias imports
+ ["parent", "sibling"], // relative imports
+ "index",
+ "object",
+ "type", // type imports
+];
+```
+
+## Next Steps
+
+To achieve 0 linting errors:
+
+1. Fix the 7 code quality errors (highest priority)
+2. Decide on import order strategy (manual fix vs. rule adjustment)
+3. Address accessibility warnings
+4. Consider adding pre-commit hooks to enforce linting
diff --git a/.agent/workflows/react-19-features.md b/.agent/workflows/react-19-features.md
new file mode 100644
index 000000000..f33264f5b
--- /dev/null
+++ b/.agent/workflows/react-19-features.md
@@ -0,0 +1,148 @@
+---
+description: React 19 Features Implementation Plan
+---
+
+# React 19 Features Implementation Plan
+
+This document outlines the recommended React 18/19 features to implement in the DevBcn codebase.
+
+## Phase 1: Quick Wins (High Impact, Low Effort)
+
+### 1. Document Metadata Support
+
+**Priority**: HIGH
+**Effort**: LOW
+**Impact**: Improves SEO, simplifies code
+
+**Implementation**:
+
+- Replace any react-helmet usage with native React 19 metadata
+- Add `
`, ``, and `` tags directly in page components
+- Update year-specific pages (2023, 2024, 2025, 2026) with proper metadata
+
+**Files to update**:
+
+- `src/views/Home/HomeWrapper.tsx`
+- `src/2023/Home/Home2023Wrapper.tsx`
+- `src/2024/Home/HomeWrapper2024.tsx`
+- `src/2025/Home/HomeWrapper2025.tsx`
+- All major page components
+
+### 2. Resource Preloading
+
+**Priority**: HIGH
+**Effort**: LOW
+**Impact**: Faster page loads
+
+**Implementation**:
+
+- Add `preconnect` for Sessionize API
+- Add `preload` for critical fonts and images (Logo)
+- Add `prefetchDNS` for external resources
+
+**Files to update**:
+
+- `src/index.tsx` (global preloads)
+- Major route components
+
+### 3. Enhanced Suspense Boundaries
+
+**Priority**: MEDIUM
+**Effort**: LOW
+**Impact**: Better loading states
+
+**Implementation**:
+
+- Wrap async data fetching components with Suspense
+- Add better fallback components
+- Improve error boundaries
+
+**Files to update**:
+
+- `src/components/Router/SuspenseRoute.tsx`
+- Data-fetching components
+
+## Phase 2: Data Fetching Improvements (Medium Effort)
+
+### 4. Migrate to `use()` Hook
+
+**Priority**: MEDIUM
+**Effort**: MEDIUM
+**Impact**: Cleaner async code
+
+**Implementation**:
+
+- Gradually migrate from react-query to `use()` API
+- Start with simple data fetching hooks
+- Keep react-query for complex caching needs
+
+**Files to update**:
+
+- `src/hooks/useFetchSpeakers.ts`
+- `src/hooks/useFetchTalks.ts`
+- Other data fetching hooks
+
+## Phase 3: Advanced Features (Higher Effort)
+
+### 5. Optimistic Updates with `useOptimistic`
+
+**Priority**: LOW
+**Effort**: MEDIUM
+**Impact**: Better UX for interactive features
+
+**Implementation**:
+
+- Add to favorite/bookmark features (if any)
+- Add to voting/rating features (if any)
+- Add to any user interaction that requires server updates
+
+### 7. Ref Cleanup Functions
+
+**Priority**: LOW
+**Effort**: LOW
+**Impact**: Better resource management
+
+**Implementation**:
+
+- Review all ref usage
+- Add cleanup functions where needed
+- Focus on intersection observers, event listeners
+
+## Phase 4: Future (Experimental)
+
+### 8. React Compiler
+
+**Priority**: FUTURE
+**Effort**: LOW (once stable)
+**Impact**: Automatic performance optimization
+
+**Implementation**:
+
+- Wait for stable release
+- Enable compiler in build config
+- Remove manual `useMemo` and `useCallback`
+- Test thoroughly
+
+## Implementation Steps
+
+1. **Start with Phase 1** - Quick wins that improve performance immediately
+2. **Test thoroughly** - Ensure 80% test coverage is maintained
+3. **Monitor performance** - Use React DevTools to measure improvements
+4. **Document changes** - Update README with new patterns
+5. **Gradual migration** - Don't rush, migrate incrementally
+
+## Success Metrics
+
+- [ ] Improved Lighthouse scores
+- [ ] Faster Time to Interactive (TTI)
+- [ ] Better Core Web Vitals
+- [ ] Reduced bundle size (if removing libraries)
+- [ ] Improved developer experience
+- [ ] All tests passing with 80%+ coverage
+
+## Notes
+
+- React 19 is now stable (released December 5, 2024)
+- Most features are production-ready
+- Server Components require Next.js or similar framework
+- React Compiler is still experimental but used in production by Instagram
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index a3c45e418..4210ef791 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -19,4 +19,4 @@ updates:
- "anyulled"
ignore:
- dependency-name: "*"
- update-types: [ "version-update:semver-patch" ]
+ update-types: ["version-update:semver-patch"]
diff --git a/.github/workflows/check_spelling.yml b/.github/workflows/check_spelling.yml
index dbc884ed3..b4b5b10a2 100644
--- a/.github/workflows/check_spelling.yml
+++ b/.github/workflows/check_spelling.yml
@@ -2,27 +2,27 @@ name: check spelling
on:
pull_request:
paths:
- - '**.ts'
- - '**.tsx'
- - '**.txt'
- - '**.html'
- - '**.md'
+ - "**.ts"
+ - "**.tsx"
+ - "**.txt"
+ - "**.html"
+ - "**.md"
jobs:
spelling:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
- with:
- ref: ${{ github.head_ref }}
- - name: Cache node modules
- id: cache-npm
- uses: actions/cache@v3
- with:
- path: ~/.npm
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
- restore-keys: |
- ${{ runner.os }}-build-${{ env.cache-name }}-
- ${{ runner.os }}-build-
- ${{ runner.os }}-
- - name: Check spelling
- uses: UnicornGlobal/spellcheck-github-actions@master
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }}
+ - name: Cache node modules
+ id: cache-npm
+ uses: actions/cache@v3
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-build-${{ env.cache-name }}-
+ ${{ runner.os }}-build-
+ ${{ runner.os }}-
+ - name: Check spelling
+ uses: UnicornGlobal/spellcheck-github-actions@master
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 566a1c0a0..1eefbee10 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -13,12 +13,12 @@ name: "CodeQL"
on:
push:
- branches: [ "main" ]
+ branches: ["main"]
pull_request:
# The branches below must be a subset of the branches above
- branches: [ "main" ]
+ branches: ["main"]
schedule:
- - cron: '29 19 * * 5'
+ - cron: "29 19 * * 5"
jobs:
analyze:
@@ -32,43 +32,42 @@ jobs:
strategy:
fail-fast: false
matrix:
- language: [ 'javascript' ]
+ language: ["javascript"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- - name: Checkout repository
- uses: actions/checkout@v3
+ - name: Checkout repository
+ uses: actions/checkout@v3
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v3
- with:
- languages: ${{ matrix.language }}
- # If you wish to specify custom queries, you can do so here or in a config file.
- # By default, queries listed here will override any specified in a config file.
- # Prefix the list here with "+" to use these queries and those in the config file.
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
- # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
- # queries: security-extended,security-and-quality
+ # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
+ # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v3
- # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@v3
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- # ℹ️ Command-line programs to run using the OS shell.
- # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+ # If the Autobuild fails above, remove it and uncomment the following three lines.
+ # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
- # If the Autobuild fails above, remove it and uncomment the following three lines.
- # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
+ # - run: |
+ # echo "Run, Build Application using script"
+ # ./location_of_script_within_repo/buildscript.sh
- # - run: |
- # echo "Run, Build Application using script"
- # ./location_of_script_within_repo/buildscript.sh
-
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v3
- with:
- category: "/language:${{matrix.language}}"
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index a47af31e8..a20e8efb6 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -2,7 +2,7 @@ name: deploy website
on:
push:
- branches: [ "main" ]
+ branches: ["main"]
jobs:
build:
@@ -22,7 +22,7 @@ jobs:
VITE_MAP_API_KEY: ${{ secrets.VITE_MAP_API_KEY }}
run: |
missing=false
-
+
for var in VITE_GOOGLE_ANALYTICS_API_KEY VITE_MAP_API_KEY; do
if [ -z "${!var}" ]; then
echo "❌ $var is not set"
@@ -31,14 +31,12 @@ jobs:
echo "✅ $var is set"
fi
done
-
+
if [ "$missing" = true ]; then
echo "::error ::One or more required env vars are missing"
exit 1
fi
-
-
- name: Use Node.js 24.x
uses: actions/setup-node@v3
with:
@@ -55,7 +53,6 @@ jobs:
${{ runner.os }}-build-
${{ runner.os }}-
-
- name: Build & deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
deleted file mode 100644
index 08f2e5116..000000000
--- a/.github/workflows/sonarcloud.yml
+++ /dev/null
@@ -1,52 +0,0 @@
-name: sonar analysis
-
-on:
- push:
- branches: ["main"]
- pull_request:
- types: [opened, synchronize, reopened]
-
-jobs:
- sonarcloud:
- name: SonarCloud
- runs-on: ubuntu-latest
- env:
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
-
- steps:
- # Checkout
- - name: checkout
- uses: actions/checkout@v3
- with:
- fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- # Load cache modules
- - name: Cache node modules
- id: cache-npm
- uses: actions/cache@v3
- env:
- cache-name: cache-node-modules
- with:
- path: ~/.npm
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
- restore-keys: |
- ${{ runner.os }}-build-${{ env.cache-name }}-
- ${{ runner.os }}-build-
- ${{ runner.os }}-
-
- # Run tests with coverage
- - name: Use Node.js 20.x
- uses: actions/setup-node@v3
- with:
- node-version: 20.x
-
- - name: run tests with coverage
- run: |
- npm ci
- npm run test-coverage
-
- # Send report to sonar
- - name: SonarCloud Scan
- uses: SonarSource/sonarqube-scan-action@v6.0.0
- env:
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 20fef2c82..af865a5ba 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -2,9 +2,9 @@ name: Unit tests
on:
push:
- branches: [ "main" ]
+ branches: ["main"]
pull_request:
- branches: [ "main" ]
+ branches: ["main"]
jobs:
build:
@@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
- node-version: [ 22.x ]
+ node-version: [22.x]
steps:
- uses: actions/checkout@v3
@@ -25,7 +25,7 @@ jobs:
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
- ${{ runner.os }}-
+ ${{ runner.os }}-
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
diff --git a/.github/workflows/webpack.yml b/.github/workflows/webpack.yml
index b699fb9b9..e813c4660 100644
--- a/.github/workflows/webpack.yml
+++ b/.github/workflows/webpack.yml
@@ -2,9 +2,9 @@ name: Build website
on:
push:
- branches: [ "main" ]
+ branches: ["main"]
pull_request:
- branches: [ "main" ]
+ branches: ["main"]
jobs:
build:
@@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
- node-version: [ 20.x, 22.x, 24.x ]
+ node-version: [20.x, 22.x, 24.x]
steps:
- uses: actions/checkout@v3
diff --git a/.junie/guidelines.md b/.junie/guidelines.md
index 81c0bdbb4..f83488308 100644
--- a/.junie/guidelines.md
+++ b/.junie/guidelines.md
@@ -23,11 +23,11 @@ speaker profiles, talk details, venue information, and registration.
The project follows a standard React application structure:
- `src/`: Source code
- - `assets/`: Static assets like images
- - `components/`: Reusable UI components
- - `hooks/`: Custom React hooks (e.g., useFetchSpeakers, useFetchTalks)
- - `views/`: Page components
- - `2024/`: Components specific to the 2024 conference
+ - `assets/`: Static assets like images
+ - `components/`: Reusable UI components
+ - `hooks/`: Custom React hooks (e.g., useFetchSpeakers, useFetchTalks)
+ - `views/`: Page components
+ - `2024/`: Components specific to the 2024 conference
## Development Workflow
@@ -61,4 +61,4 @@ When contributing to this project, please:
For questions or issues related to the DevBcn website, please open an issue in
this repository.
-Visit the live site at [https://www.devbcn.com](https://www.devbcn.com)
\ No newline at end of file
+Visit the live site at [https://www.devbcn.com](https://www.devbcn.com)
diff --git a/.vscode/launch.json b/.vscode/launch.json
index fdaedb981..593dcc815 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,14 +1,14 @@
{
- // Use IntelliSense to learn about possible attributes.
- // Hover to view descriptions of existing attributes.
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
- "version": "0.2.0",
- "configurations": [
- {
- "command": "npm start",
- "name": "Run npm start",
- "request": "launch",
- "type": "node-terminal"
- },
- ]
-}
\ No newline at end of file
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "command": "npm start",
+ "name": "Run npm start",
+ "request": "launch",
+ "type": "node-terminal"
+ }
+ ]
+}
diff --git a/docs/PageMetadata-Usage.md b/docs/PageMetadata-Usage.md
new file mode 100644
index 000000000..f2bdf5493
--- /dev/null
+++ b/docs/PageMetadata-Usage.md
@@ -0,0 +1,214 @@
+# PageMetadata Component - Usage Guide
+
+## Overview
+
+The `PageMetadata` component leverages React 19's native metadata support to render SEO tags directly in your components without needing external libraries like `react-helmet`.
+
+## Quick Start
+
+### Basic Usage
+
+```tsx
+import { PageMetadata } from "@components/common/PageMetadata";
+
+export const MyPage = () => {
+ return (
+ <>
+
+
+ {/* Your page content */}
+ >
+ );
+};
+```
+
+### Using Centralized Configuration
+
+For consistency across the site, use the centralized metadata configuration:
+
+```tsx
+import { PageMetadata } from "@components/common/PageMetadata";
+import { getPageMetadata } from "@config/metadata";
+
+export const HomeWrapper2025 = () => {
+ return (
+ <>
+
+
+ {/* Your page content */}
+ >
+ );
+};
+```
+
+## Advanced Usage
+
+### Custom Metadata
+
+```tsx
+
+```
+
+### Dynamic Metadata
+
+```tsx
+export const SpeakerDetailPage = ({ speaker }) => {
+ return (
+ <>
+
+
+ {/* Speaker content */}
+ >
+ );
+};
+```
+
+## Props Reference
+
+| Prop | Type | Required | Default | Description |
+| -------------- | ------------------------------------ | -------- | ----------------------- | -------------------------- | ----------------------- |
+| `title` | `string` | ✅ | - | Page title (will append " | DevBcn" if not present) |
+| `description` | `string` | ✅ | - | Page description for SEO |
+| `canonicalUrl` | `string` | ❌ | - | Canonical URL for the page |
+| `ogImage` | `string` | ❌ | Default OG image | Open Graph image URL |
+| `ogType` | `"website" \| "article" \| "event"` | ❌ | `"website"` | Open Graph type |
+| `twitterCard` | `"summary" \| "summary_large_image"` | ❌ | `"summary_large_image"` | Twitter card type |
+| `keywords` | `string[]` | ❌ | `[]` | SEO keywords |
+
+## Adding New Pages to Configuration
+
+To add a new page to the centralized configuration:
+
+1. Open `src/config/metadata.ts`
+2. Add your page to the `METADATA_CONFIG` object:
+
+```typescript
+export const METADATA_CONFIG = {
+ // ... existing pages
+
+ myNewPage: {
+ title: "My New Page - DevBcn",
+ description: "Description of my new page",
+ canonicalUrl: `${BASE_URL}/my-new-page`,
+ ogImage: `${BASE_URL}/images/my-new-page.jpg`,
+ keywords: ["keyword1", "keyword2"],
+ },
+};
+```
+
+3. Use it in your component:
+
+```tsx
+
+```
+
+## Migration from react-helmet
+
+If you're migrating from `react-helmet`, here's the comparison:
+
+### Before (react-helmet)
+
+```tsx
+import { Helmet } from "react-helmet";
+
+
+ My Page | DevBcn
+
+
+;
+```
+
+### After (React 19 Native)
+
+```tsx
+import { PageMetadata } from "@components/common/PageMetadata";
+
+;
+```
+
+## Benefits
+
+✅ **No External Dependencies** - Uses React 19's native features
+✅ **Type-Safe** - Full TypeScript support
+✅ **Centralized** - All metadata in one configuration file
+✅ **Consistent** - Automatic title formatting
+✅ **SEO-Friendly** - Includes all essential meta tags
+✅ **Social Media Ready** - Open Graph and Twitter cards included
+
+## Testing
+
+The component includes comprehensive tests. To run them:
+
+```bash
+npm test -- PageMetadata
+```
+
+## Best Practices
+
+1. **Always provide title and description** - These are essential for SEO
+2. **Use the centralized config** - Keeps metadata consistent
+3. **Include canonical URLs** - Helps with duplicate content issues
+4. **Provide OG images** - Improves social media sharing
+5. **Use descriptive keywords** - But don't keyword stuff
+6. **Keep descriptions under 160 characters** - For optimal display in search results
+7. **Make titles unique** - Each page should have a distinct title
+
+## Examples by Page Type
+
+### Home Page
+
+```tsx
+
+```
+
+### Content Page (Speakers, Talks, etc.)
+
+```tsx
+
+```
+
+### Dynamic Detail Page
+
+```tsx
+
+```
+
+## Troubleshooting
+
+**Q: The title doesn't appear in the browser tab**
+A: Make sure the `PageMetadata` component is rendered. Check React DevTools to verify it's in the component tree.
+
+**Q: Meta tags aren't showing in view source**
+A: React 19's metadata is rendered client-side. For SSR, you'll need a framework like Next.js.
+
+**Q: Can I use multiple PageMetadata components?**
+A: Only use one per page. The last one rendered will take precedence.
+
+**Q: How do I test if metadata is working?**
+A: Use browser DevTools to inspect the `` element, or use tools like [metatags.io](https://metatags.io/) to preview social cards.
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 000000000..b881fb8a4
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,140 @@
+import js from "@eslint/js";
+import tseslint from "@typescript-eslint/eslint-plugin";
+import tsparser from "@typescript-eslint/parser";
+import importPlugin from "eslint-plugin-import";
+import jsxA11y from "eslint-plugin-jsx-a11y";
+import react from "eslint-plugin-react";
+import reactHooks from "eslint-plugin-react-hooks";
+import reactRefresh from "eslint-plugin-react-refresh";
+import globals from "globals";
+
+export default [
+ {
+ ignores: [
+ "dist",
+ "build",
+ "node_modules",
+ "coverage",
+ "*.config.js",
+ "*.config.ts",
+ "public",
+ "scripts",
+ ],
+ },
+ {
+ files: ["**/*.{ts,tsx}"],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: {
+ ...globals.browser,
+ ...globals.node,
+ // Vitest globals
+ describe: "readonly",
+ it: "readonly",
+ test: "readonly",
+ expect: "readonly",
+ beforeEach: "readonly",
+ afterEach: "readonly",
+ beforeAll: "readonly",
+ afterAll: "readonly",
+ vi: "readonly",
+ },
+ parser: tsparser,
+ parserOptions: {
+ ecmaVersion: "latest",
+ ecmaFeatures: { jsx: true },
+ sourceType: "module",
+ },
+ },
+ settings: {
+ react: { version: "18.3" },
+ "import/resolver": {
+ typescript: {
+ alwaysTryTypes: true,
+ project: "./tsconfig.json",
+ },
+ alias: {
+ map: [
+ ["@", "./src"],
+ ["@components", "./src/components"],
+ ["@views", "./src/views"],
+ ["@utils", "./src/utils"],
+ ["@hooks", "./src/hooks"],
+ ["@types", "./src/types"],
+ ["@assets", "./src/assets"],
+ ],
+ extensions: [".ts", ".tsx", ".js", ".jsx", ".json"],
+ },
+ },
+ },
+ plugins: {
+ react,
+ "react-hooks": reactHooks,
+ "react-refresh": reactRefresh,
+ "@typescript-eslint": tseslint,
+ "jsx-a11y": jsxA11y,
+ import: importPlugin,
+ },
+ rules: {
+ ...js.configs.recommended.rules,
+ ...tseslint.configs.recommended.rules,
+ ...react.configs.recommended.rules,
+ ...react.configs["jsx-runtime"].rules,
+ ...reactHooks.configs.recommended.rules,
+
+ // TypeScript specific rules
+ "@typescript-eslint/no-explicit-any": "error",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off",
+ "@typescript-eslint/no-unused-vars": [
+ "error",
+ {
+ argsIgnorePattern: "^_",
+ varsIgnorePattern: "^_",
+ caughtErrorsIgnorePattern: "^_",
+ },
+ ],
+ "@typescript-eslint/no-non-null-assertion": "warn",
+ "@typescript-eslint/consistent-type-imports": [
+ "error",
+ {
+ prefer: "type-imports",
+ disallowTypeAnnotations: false,
+ },
+ ],
+
+ // React specific rules
+ "react/react-in-jsx-scope": "off",
+ "react/prop-types": "off",
+ "react/jsx-uses-react": "off",
+ "react-refresh/only-export-components": [
+ "warn",
+ { allowConstantExport: true },
+ ],
+
+ // Import rules
+ "import/order": "off", // Disabled - too strict and tedious to maintain
+ "import/no-duplicates": "error",
+ "import/no-unresolved": "error",
+ "import/named": "error",
+ "import/default": "error",
+
+ // General code quality rules
+ "no-console": ["warn", { allow: ["warn", "error"] }],
+ "no-debugger": "warn",
+ "prefer-const": "error",
+ "no-var": "error",
+ "object-shorthand": "error",
+ "quote-props": ["error", "as-needed"],
+ eqeqeq: ["error", "always", { null: "ignore" }],
+ "no-unused-expressions": "off", // Disabled for styled-components
+ "no-undef": "off", // TypeScript handles this better
+
+ // Accessibility rules
+ "jsx-a11y/alt-text": "warn",
+ "jsx-a11y/anchor-is-valid": "warn",
+ "jsx-a11y/click-events-have-key-events": "warn",
+ "jsx-a11y/no-static-element-interactions": "warn",
+ },
+ },
+];
diff --git a/index.html b/index.html
index dbdfa0319..d0909329f 100644
--- a/index.html
+++ b/index.html
@@ -1,301 +1,409 @@
-
+
-
-
-
- DevBcn 2025 - Barcelona Developers Conference in Spain — July
- 08-10
-
-
-
+
+
+
+
+ DevBcn 2025 - Barcelona Developers Conference in Spain — July 08-10
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
\ No newline at end of file
+ //]]>
+
+
+
diff --git a/package-lock.json b/package-lock.json
index 1063e101b..ac317a264 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,9 +17,9 @@
"@sentry/tracing": "^7.120.3",
"@sentry/vite-plugin": "^4.6.1",
"@types/jest": "^30.0.0",
- "@types/node": "^25.0.3",
- "@types/react": "^18.3.5",
- "@types/react-dom": "^18.3.0",
+ "@types/node": "^24.0.8",
+ "@types/react": "^19.0.0",
+ "@types/react-dom": "^19.0.0",
"add-to-calendar-button-react": "^2.8.1",
"axios": "^1.13.2",
"bootstrap": "^5.3.6",
@@ -34,11 +34,11 @@
"motion": "^12.23.9",
"primeicons": "^7.0.0",
"primereact": "^10.9.1",
- "react": "^18.3.1",
+ "react": "^19.0.0",
"react-bootstrap": "^2.10.10",
"react-cookie-consent": "^9.0.0",
"react-countdown": "^2.3.6",
- "react-dom": "^18.3.1",
+ "react-dom": "^19.0.0",
"react-icons": "^5.5.0",
"react-qr-code": "^2.0.18",
"react-query": "^3.39.2",
@@ -76,13 +76,14 @@
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.26",
"gh-pages": "^6.3.0",
"globals": "^16.5.0",
"jsdom": "^27.3.0",
"postcss": "^8.5.3",
"prettier": "^3.6.2",
"react-ga": "^3.3.1",
- "react-test-renderer": "^18.3.1",
+ "react-test-renderer": "^19.0.0",
"rollup-plugin-visualizer": "^6.0.3",
"tailwindcss": "^4.1.11",
"vite": "^7.1.12",
@@ -4723,12 +4724,11 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "25.0.3",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz",
- "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==",
- "license": "MIT",
+ "version": "24.0.8",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.8.tgz",
+ "integrity": "sha512-WytNrFSgWO/esSH9NbpWUfTMGQwCGIKfCmNlmFDNiI5gGhgMmEA+V1AEvKLeBNvvtBnailJtkrEa2OIISwrVAA==",
"dependencies": {
- "undici-types": "~7.16.0"
+ "undici-types": "~7.8.0"
}
},
"node_modules/@types/prop-types": {
@@ -4738,22 +4738,21 @@
"license": "MIT"
},
"node_modules/@types/react": {
- "version": "18.3.20",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz",
- "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==",
+ "version": "19.2.7",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
+ "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
"license": "MIT",
"dependencies": {
- "@types/prop-types": "*",
- "csstype": "^3.0.2"
+ "csstype": "^3.2.2"
}
},
"node_modules/@types/react-dom": {
- "version": "18.3.5",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz",
- "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==",
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"license": "MIT",
"peerDependencies": {
- "@types/react": "^18.0.0"
+ "@types/react": "^19.2.0"
}
},
"node_modules/@types/react-router": {
@@ -4798,6 +4797,12 @@
"@types/react": "*"
}
},
+ "node_modules/@types/react/node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "license": "MIT"
+ },
"node_modules/@types/resolve": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
@@ -7991,6 +7996,16 @@
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
}
},
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.26",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz",
+ "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "eslint": ">=8.40"
+ }
+ },
"node_modules/eslint-plugin-react/node_modules/resolve": {
"version": "2.0.0-next.5",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
@@ -11671,13 +11686,10 @@
}
},
"node_modules/react": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
- "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
+ "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"license": "MIT",
- "dependencies": {
- "loose-envify": "^1.1.0"
- },
"engines": {
"node": ">=0.10.0"
}
@@ -11742,16 +11754,15 @@
}
},
"node_modules/react-dom": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
- "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"license": "MIT",
"dependencies": {
- "loose-envify": "^1.1.0",
- "scheduler": "^0.23.2"
+ "scheduler": "^0.27.0"
},
"peerDependencies": {
- "react": "^18.3.1"
+ "react": "^19.2.3"
}
},
"node_modules/react-error-boundary": {
@@ -11890,39 +11901,24 @@
"react-dom": ">=18"
}
},
- "node_modules/react-shallow-renderer": {
- "version": "16.15.0",
- "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz",
- "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "object-assign": "^4.1.1",
- "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0"
- },
- "peerDependencies": {
- "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
- }
- },
"node_modules/react-test-renderer": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.3.1.tgz",
- "integrity": "sha512-KkAgygexHUkQqtvvx/otwxtuFu5cVjfzTCtjXLH9boS19/Nbtg84zS7wIQn39G8IlrhThBpQsMKkq5ZHZIYFXA==",
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-19.2.3.tgz",
+ "integrity": "sha512-TMR1LnSFiWZMJkCgNf5ATSvAheTT2NvKIwiVwdBPHxjBI7n/JbWd4gaZ16DVd9foAXdvDz+sB5yxZTwMjPRxpw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "react-is": "^18.3.1",
- "react-shallow-renderer": "^16.15.0",
- "scheduler": "^0.23.2"
+ "react-is": "^19.2.3",
+ "scheduler": "^0.27.0"
},
"peerDependencies": {
- "react": "^18.3.1"
+ "react": "^19.2.3"
}
},
"node_modules/react-test-renderer/node_modules/react-is": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.3.tgz",
+ "integrity": "sha512-qJNJfu81ByyabuG7hPFEbXqNcWSU3+eVus+KJs+0ncpGfMyYdvSmxiJxbWR65lYi1I+/0HBcliO029gc4F+PnA==",
"dev": true,
"license": "MIT"
},
@@ -12479,13 +12475,10 @@
}
},
"node_modules/scheduler": {
- "version": "0.23.2",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
- "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
- "license": "MIT",
- "dependencies": {
- "loose-envify": "^1.1.0"
- }
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
},
"node_modules/screenfull": {
"version": "5.2.0",
@@ -13832,10 +13825,9 @@
}
},
"node_modules/undici-types": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
- "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
- "license": "MIT"
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
+ "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="
},
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.1",
diff --git a/package.json b/package.json
index f4db0f1a5..d4ea5bd54 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,6 @@
{
"name": "devbcn",
+ "type": "module",
"homepage": "https://www.devbcn.com",
"version": "1.5.0",
"private": true,
@@ -10,9 +11,9 @@
"@sentry/tracing": "^7.120.3",
"@sentry/vite-plugin": "^4.6.1",
"@types/jest": "^30.0.0",
- "@types/node": "^25.0.3",
- "@types/react": "^18.3.5",
- "@types/react-dom": "^18.3.0",
+ "@types/node": "^24.0.8",
+ "@types/react": "^19.0.0",
+ "@types/react-dom": "^19.0.0",
"add-to-calendar-button-react": "^2.8.1",
"axios": "^1.13.2",
"bootstrap": "^5.3.6",
@@ -27,11 +28,11 @@
"motion": "^12.23.9",
"primeicons": "^7.0.0",
"primereact": "^10.9.1",
- "react": "^18.3.1",
+ "react": "^19.0.0",
"react-bootstrap": "^2.10.10",
"react-cookie-consent": "^9.0.0",
"react-countdown": "^2.3.6",
- "react-dom": "^18.3.1",
+ "react-dom": "^19.0.0",
"react-icons": "^5.5.0",
"react-qr-code": "^2.0.18",
"react-query": "^3.39.2",
@@ -93,13 +94,14 @@
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.26",
"gh-pages": "^6.3.0",
"globals": "^16.5.0",
"jsdom": "^27.3.0",
"postcss": "^8.5.3",
"prettier": "^3.6.2",
"react-ga": "^3.3.1",
- "react-test-renderer": "^18.3.1",
+ "react-test-renderer": "^19.0.0",
"rollup-plugin-visualizer": "^6.0.3",
"tailwindcss": "^4.1.11",
"vite": "^7.1.12",
diff --git a/public/404.html b/public/404.html
index 214cee2d5..dfc498239 100644
--- a/public/404.html
+++ b/public/404.html
@@ -1,40 +1,50 @@
-
+
-
-
- DevBCN
+
+
+ DevBCN
-
-
-
+
+
diff --git a/public/images/venue/venue-1.webp b/public/images/venue/venue-1.webp
new file mode 100644
index 000000000..30ddf4b05
Binary files /dev/null and b/public/images/venue/venue-1.webp differ
diff --git a/public/images/venue/venue-2.webp b/public/images/venue/venue-2.webp
new file mode 100644
index 000000000..6202bb806
Binary files /dev/null and b/public/images/venue/venue-2.webp differ
diff --git a/public/images/venue/venue-3.webp b/public/images/venue/venue-3.webp
new file mode 100644
index 000000000..b6135ac83
Binary files /dev/null and b/public/images/venue/venue-3.webp differ
diff --git a/public/images/venue/venue-4.webp b/public/images/venue/venue-4.webp
new file mode 100644
index 000000000..88db5c84d
Binary files /dev/null and b/public/images/venue/venue-4.webp differ
diff --git a/public/images/venue/venue-5.webp b/public/images/venue/venue-5.webp
new file mode 100644
index 000000000..2f4f7e8f9
Binary files /dev/null and b/public/images/venue/venue-5.webp differ
diff --git a/public/images/wtc-gemini-1.webp b/public/images/wtc-gemini-1.webp
new file mode 100644
index 000000000..8b7435742
Binary files /dev/null and b/public/images/wtc-gemini-1.webp differ
diff --git a/public/images/wtc-gemini-2.webp b/public/images/wtc-gemini-2.webp
new file mode 100644
index 000000000..37ee287de
Binary files /dev/null and b/public/images/wtc-gemini-2.webp differ
diff --git a/public/images/wtc-gemini-3.webp b/public/images/wtc-gemini-3.webp
new file mode 100644
index 000000000..e7473518c
Binary files /dev/null and b/public/images/wtc-gemini-3.webp differ
diff --git a/public/index.html b/public/index.html
index ab06f3a9e..d79d7afa0 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,68 +1,75 @@
-
+
-
-
-
- DevBcn 2025 - Barcelona Developers Conference in Spain — July
- 08-10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+ window.history.replaceState(
+ null,
+ null,
+ l.pathname.slice(0, -1) + decoded + l.hash,
+ );
+ }
+ })(window.location);
+
-
-
+
-
-
-
-
-
-
-
+ //]]>
+
+