Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
243 commits
Select commit Hold shift + click to select a range
ab68855
gfi and homepage
corwintines Dec 11, 2025
e167287
migrate apps to data layer
corwintines Dec 11, 2025
edfddc8
migrate rest of pages
corwintines Dec 11, 2025
0c54c43
cleanup old mocks and api folder
corwintines Dec 11, 2025
8f84627
deprecate old dataLoader functions
corwintines Dec 11, 2025
7928b6e
Merge branch 'datalayer-layer2' into datalayer-pages
corwintines Dec 16, 2025
80eaa03
fix: remove horizontal line from expanded wallet accordion
wackerow Dec 17, 2025
019c28d
Merge branch 'datalayer-layer2' into datalayer-pages
corwintines Dec 17, 2025
4ee3192
Fix critical pbkdf2 vulnerabilities (CVE)
minimalsm Dec 18, 2025
ab1afe4
Merge branch 'dev' into datalayer-pages
pettinarip Dec 19, 2025
a554aad
update netlify included_files path to data-layer/mocks
pettinarip Dec 19, 2025
a65e293
Update Crowdin translation progress
actions-user Dec 19, 2025
fe513f0
Add external tutorial: Remix vs Truffle vs Hardhat vs Foundry
wackerow Dec 19, 2025
05440f6
chore: update claude-code-action to v1
wackerow Dec 19, 2025
14a9f8b
chore: update link to redirected URL
wackerow Dec 19, 2025
e5452d0
Fix critical form-data vulnerability (CVE)
wackerow Jan 6, 2026
6e292d1
feat: add Geode Labs events API integration
wackerow Jan 6, 2026
7e7259b
refactor: use Geode Labs API for homepage events
wackerow Jan 6, 2026
1216c60
update: community hubs with IDs and styling
wackerow Jan 6, 2026
c35ffc9
feat: add community events page with filtering and views
wackerow Jan 6, 2026
51999c5
update: ui/section scrollMargin variant
wackerow Jan 6, 2026
a162ba0
update: community hub data
wackerow Jan 6, 2026
76c5e03
update: community events iteration
wackerow Jan 6, 2026
7ef7162
feat: add date range utility helper
wackerow Jan 7, 2026
5e54089
update: events cards
wackerow Jan 7, 2026
cbd0f8e
import: continent svg icons
wackerow Jan 7, 2026
313b2c3
temp: demo array meetups
wackerow Jan 7, 2026
b70bce2
feat: add onSelect functionality to TabNav
wackerow Jan 7, 2026
71a0bd6
update: continent tabs
wackerow Jan 7, 2026
fe5a118
update: continent event rows
wackerow Jan 7, 2026
8a7619e
update: events sections and images
wackerow Jan 7, 2026
0305859
refactor: meetup events to EventCard grid
wackerow Jan 7, 2026
824a9cd
feat: add prepare-release command
wackerow Jan 8, 2026
538d496
feat: enable execution outside of dev via git worktree
wackerow Jan 8, 2026
f9d66c1
feat: add --dry-run flag
wackerow Jan 8, 2026
1059c2a
patch: node command syntax
wackerow Jan 8, 2026
d3dfbfd
fix: improve prepare-release reliability
wackerow Jan 8, 2026
b0d63f3
Import old trigger.dev revalidation tasks for backward compatibility
pettinarip Jan 8, 2026
b4bae8b
Add Zircuit Layer 2 network
Jan 8, 2026
c43dafa
Merge pull request #17029 from ethereum/prepare-release
pettinarip Jan 8, 2026
7f93dbb
Merge branch 'dev' into datalayer-pages
pettinarip Jan 8, 2026
400d4f7
Standardize null handling for data fetching
pettinarip Jan 8, 2026
f105a30
Add proper typing for stablecoins data
pettinarip Jan 8, 2026
2beea72
Merge branch 'dev' into events-revamp
wackerow Jan 8, 2026
4046306
refactor: Update Chains workflow to use gh CLI
wackerow Jan 8, 2026
104083c
Update chains data
actions-user Jan 8, 2026
0e07b67
Add workflow to cleanup stale Netlify preview deploys
Jan 8, 2026
8404951
Merge pull request #17039 from ethereum/automated-update-20260108174032
wackerow Jan 8, 2026
e9b53e5
Merge pull request #17038 from minimalsm/chore/netlify-preview-cleanup
minimalsm Jan 8, 2026
d4cce63
patch: network name
wackerow Jan 8, 2026
9cdd76f
Enable Netlify preview cleanup and protect staging/dev branches
Jan 8, 2026
2e2590e
Merge pull request #17040 from minimalsm/chore/netlify-cleanup-enable…
pettinarip Jan 8, 2026
06611ce
feat: update CLAUDE with chain names typing details
wackerow Jan 8, 2026
1cf4bba
Increase Netlify cleanup pagination to 10,000 deploys
Jan 8, 2026
52acc67
Merge pull request #17042 from minimalsm/chore/netlify-cleanup-pagina…
minimalsm Jan 8, 2026
f6c97a3
patch: hub card images
wackerow Jan 8, 2026
09c2f79
patch: callout card styling
wackerow Jan 8, 2026
11d891e
Merge pull request #17034 from ethereum/import-old-trigger-tasks
wackerow Jan 8, 2026
4ce8b17
Merge branch 'dev' into feature/add-zircuit-layer2
wackerow Jan 8, 2026
846f2b3
dev: add zircuit mock data
wackerow Jan 8, 2026
96b36b9
fix: add fallback for missing network maturity data
wackerow Jan 8, 2026
069c1e9
build: npx update-browserslist-db@latest
wackerow Jan 8, 2026
370afb8
feat: add options? param to formatDate
wackerow Jan 8, 2026
9f87feb
patch(ui): spacing, styling, formatting
wackerow Jan 8, 2026
4dfdec5
feat: add mock data
wackerow Jan 8, 2026
c61dd35
update(ui): ContentHero className prop, TabNav mobile border
wackerow Jan 9, 2026
5bce299
update(ui): mobile adjustments
wackerow Jan 9, 2026
06713d5
deprecate: markdown events page
wackerow Jan 9, 2026
6d0a8df
feat: hub card swiper, dark mode, i18n
wackerow Jan 9, 2026
667abcc
feat: add getLocaleYear helper
wackerow Jan 9, 2026
79c0e1e
refactor: ContentHero for optional hero image
wackerow Jan 9, 2026
5baafe6
update: OrganizerCTA, date util usage
wackerow Jan 9, 2026
e596a3e
update: ContintentTabs, EventCard, intl strings
wackerow Jan 9, 2026
d97a34f
Merge pull request #17036 from ethereum/feature/add-zircuit-layer2
wackerow Jan 9, 2026
8f57175
Fix mobile menu scrolling in Safari
pettinarip Jan 9, 2026
bd9732a
Fix 404s on markdown pages by avoiding ISR trigger
pettinarip Jan 9, 2026
ed4247b
Update Mirror.xyz RSS feeds to use Paragraph API
pettinarip Jan 9, 2026
d070968
Update @trigger.dev/sdk to 4.3.2 and add deploy script
pettinarip Jan 9, 2026
014379a
Update Crowdin translation progress
actions-user Jan 9, 2026
1d459e4
patch: use fallback image if src undefined
wackerow Jan 9, 2026
006b0a7
Merge pull request #17046 from ethereum/fix/mirror-rss-feeds-to-parag…
wackerow Jan 9, 2026
89fa8eb
patch: add back "update" label to workflow
wackerow Jan 9, 2026
d1d4397
Merge pull request #16953 from ethereum/fix/wallet-accordion-line
pettinarip Jan 9, 2026
61ae6c2
Merge pull request #16961 from ethereum/add-external-tutorial-14330
pettinarip Jan 9, 2026
e61f4c9
Merge pull request #16963 from ethereum/chore/update-claude-action
pettinarip Jan 9, 2026
1bc288e
Merge pull request #17037 from ethereum/fix/update-chains-workflow-pe…
pettinarip Jan 9, 2026
9c1b1f3
Merge pull request #17043 from ethereum/caniuse-lite
pettinarip Jan 9, 2026
25838b8
Merge pull request #16859 from ethereum/datalayer-pages
pettinarip Jan 9, 2026
11d294a
feat: add client-side meetups Filter component
wackerow Jan 9, 2026
4580ccd
update: meetups page
wackerow Jan 9, 2026
b3254c4
update: ui, links, comments
wackerow Jan 9, 2026
fbbc813
feat(ui): add accent color variants to ui/tag
wackerow Jan 9, 2026
1f9c5c7
refactor: FilterMeetups
wackerow Jan 9, 2026
29f9f0d
feat: add optional showTypeTag to EventCard
wackerow Jan 9, 2026
95c98c3
feat: FilterEvents (refactor SearchSection)
wackerow Jan 9, 2026
f20be22
refactor: reusable sanitize util
wackerow Jan 10, 2026
e471260
feat: add /search page
wackerow Jan 10, 2026
dadb767
deprecate: unused components
wackerow Jan 10, 2026
f6c418d
feat(i18n): mapEventTranslations
wackerow Jan 10, 2026
aadd789
fix: empty space in ContentHero without img
wackerow Jan 10, 2026
f975098
chore: clean up, wrap query in quotes, undo mocks
wackerow Jan 10, 2026
2092e22
fix: remove unnecessary forwardRef from AlertEmoji
wackerow Jan 10, 2026
f61de83
patch(ui): spacing, sizing, colors
wackerow Jan 10, 2026
f41b57f
feat: add sf hub, patch lagos links
wackerow Jan 10, 2026
475fbd2
fix: use sr-only over VisuallyHidden
wackerow Jan 11, 2026
d802f74
fix: use sr-only over VisuallyHidden
wackerow Jan 11, 2026
f3e3a25
fix: line-clamp class ui/TruncatedText
wackerow Jan 11, 2026
8c77b81
fix: contain sr-only in external links
wackerow Jan 11, 2026
d2e2129
fix: contain sr-only in external links
wackerow Jan 11, 2026
e3ae948
refactor: HubsSwiper to use css snap
wackerow Jan 11, 2026
5e1d499
feat: apply fade mask to edges >2xl breakpoint
wackerow Jan 11, 2026
6880574
feat(ui): add EdgeScroll* components with stories
wackerow Jan 11, 2026
7e4b666
refactor: use ui/edge-scroll* components
wackerow Jan 12, 2026
e593b10
deprecate: import community events action
wackerow Jan 12, 2026
2ebca69
Merge pull request #17047 from ethereum/chore/update-trigger-sdk-4.3.2
wackerow Jan 12, 2026
a708c5b
Merge pull request #17048 from ethereum/automated-update-20260109162932
wackerow Jan 12, 2026
0c6c1e0
Merge pull request #17044 from ethereum/fix/mobile-menu-safari-scroll
wackerow Jan 12, 2026
d918af2
feat: add JSON-LD structured data for events page
wackerow Jan 12, 2026
59d0288
patch: card width on desktop
wackerow Jan 12, 2026
50019e1
feat: add custom matomo tracking
wackerow Jan 12, 2026
9cb7483
patch: TabNav width
wackerow Jan 12, 2026
8baf50e
Update Pillar Wallet to PillarX
Jan 12, 2026
ed94a23
Fix import path for fetchApps in revalidate-apps task
pettinarip Jan 12, 2026
6ce0846
Merge pull request #17066 from ethereum/fix/revalidate-apps-import
pettinarip Jan 12, 2026
9ece3c1
Merge pull request #17052 from ethereum/fix-truncated-text
pettinarip Jan 12, 2026
535f427
Merge pull request #17049 from ethereum/fix/alert-emoji-forward-ref
pettinarip Jan 12, 2026
05a729a
Merge pull request #17041 from ethereum/claude-network-types-update
pettinarip Jan 12, 2026
0de4598
deprecate: @radix-ui/react-visually-hidden
wackerow Jan 12, 2026
d5a97da
Merge pull request #17051 from ethereum/fix-visually-hidden
wackerow Jan 12, 2026
5646ede
update: matomo analytics
wackerow Jan 12, 2026
4182efb
deprecate: MeetupList component
wackerow Jan 12, 2026
e780ca2
feat: add meetup groups to supplement sparse API data
wackerow Jan 12, 2026
53b6d11
Merge branch 'dev' into fix/update-pillar-to-pillarx
wackerow Jan 12, 2026
89464ae
Merge branch 'dev' into events-revamp
wackerow Jan 12, 2026
0fdaa1a
refactor: move getMeetupGroups to community/events/utils
wackerow Jan 12, 2026
57485e8
fix: remove networks not in canonical list
wackerow Jan 12, 2026
f9fe44e
Merge pull request #16960 from ethereum/automated-update-20251219162912
wackerow Jan 12, 2026
a7c6d3d
updates
koyahness Jan 12, 2026
a51e1e2
fix: update remaining events pages to use data-layer
wackerow Jan 13, 2026
6f2b660
updates
koyahness Jan 13, 2026
89e0174
Merge branch 'ethereum:dev' into dev
koyahness Jan 13, 2026
fd6cbd6
Merge pull request #16942 from ethereum/fix/security-form-data-vulner…
wackerow Jan 13, 2026
22eae21
Merge branch 'dev' into fix/security-pbkdf2-vulnerability
wackerow Jan 13, 2026
ec43d0c
Merge pull request #16943 from ethereum/fix/security-pbkdf2-vulnerabi…
wackerow Jan 13, 2026
24dbf3b
Merge pull request #17074 from koyahness/dev
wackerow Jan 13, 2026
c8e4002
docs: update README.md [skip ci]
allcontributors[bot] Jan 13, 2026
6cf7e19
docs: update .all-contributorsrc [skip ci]
allcontributors[bot] Jan 13, 2026
71e968b
Merge pull request #17075 from ethereum/all-contributors/add-koyahness
wackerow Jan 13, 2026
40f8506
docs: fix small naming issues
mdqst Jan 13, 2026
05b5173
deprecate(i18n): markdown events pages
wackerow Jan 13, 2026
da0c697
fix: mock data location
wackerow Jan 13, 2026
6ba9444
refactor: geography utils
wackerow Jan 13, 2026
d2ece8b
feat(ui): add primary tag color
wackerow Jan 13, 2026
be9f7dc
update(ui): show tags on all meetup event cards
wackerow Jan 13, 2026
33439e5
Merge pull request #17076 from mdqst/patch-47
wackerow Jan 13, 2026
ec995e4
patch: pillarx metadata
wackerow Jan 14, 2026
d804a4a
Merge pull request #17065 from ethereum/fix/update-pillar-to-pillarx
wackerow Jan 14, 2026
e26491e
chore: update license
davidcardenasus Jan 14, 2026
22c8ac5
refactor(perf): continent icons, simplify shapes
wackerow Jan 14, 2026
fb89c11
patch: apply adjustments from code review
wackerow Jan 14, 2026
f6afdb8
patch(i18n): add variable to intl string
wackerow Jan 14, 2026
7877a45
refactor(events): support multiple event types per event
wackerow Jan 14, 2026
0a53dc7
feat(events): add popup, regional, and other event types
wackerow Jan 14, 2026
8027039
feat(ui): additional tag color variants
wackerow Jan 14, 2026
975ffcf
refactor(events): export and reuse getEventTypes helper
wackerow Jan 15, 2026
3792e6a
refactor(events): centralize TAG_STATUS_MAPPING
wackerow Jan 15, 2026
4343ee1
fix(events): exclude conferences/hackathons from meetups
wackerow Jan 15, 2026
a302cf0
fix(events): correct search/conferences page metadata
wackerow Jan 15, 2026
ef8f063
fix(data): remove broken Ethereum Aragua image refs
wackerow Jan 15, 2026
91bea80
fix: claude regression
wackerow Jan 15, 2026
d53d713
refactor: developers page hackathons
wackerow Jan 15, 2026
10c4758
deprecate: unused events code
wackerow Jan 15, 2026
db4ec4b
refactor: use formatDateRange date util
wackerow Jan 15, 2026
d9897fe
docs: fix missing articles and align heading wording
mdqst Jan 15, 2026
afe53b1
chore: reduce events mock data and remove unused legacy mock
pettinarip Jan 15, 2026
4617495
refactor: simplify getEventsData to follow data-layer getter pattern
pettinarip Jan 15, 2026
029a98d
refactor: expose getEventsData via lib/data and update home page imports
pettinarip Jan 15, 2026
679688a
refactor: update all getEventsData imports to use cached lib/data ver…
pettinarip Jan 15, 2026
ec8bab0
docs: add data-layer key rules and Claude Code skill
pettinarip Jan 15, 2026
e468c9f
Merge pull request #17088 from ethereum/refactor/simplify-events-data…
wackerow Jan 15, 2026
88d486f
patch: event type fallback and link styling
wackerow Jan 15, 2026
714369b
fix: eventTypes type handling, hackathon logic
wackerow Jan 15, 2026
ea6525e
fix(events): compute eventTypes from tags when missing
wackerow Jan 15, 2026
798d38b
update(i18n): src/intl/zh/page-community-events.json
wackerow Jan 15, 2026
a526e32
update(i18n): src/intl/es/page-community-events.json
wackerow Jan 15, 2026
52d21fd
update(i18n): src/intl/hi/page-community-events.json
wackerow Jan 15, 2026
71d1e35
update(i18n): src/intl/ar/page-community-events.json
wackerow Jan 15, 2026
07a66c4
update(i18n): src/intl/pt-br/page-community-events.json
wackerow Jan 15, 2026
1c26a01
update(i18n): src/intl/fr/page-community-events.json
wackerow Jan 15, 2026
1aee380
update(i18n): src/intl/id/page-community-events.json
wackerow Jan 15, 2026
9e38712
update(i18n): src/intl/ru/page-community-events.json
wackerow Jan 15, 2026
2919ac2
update(i18n): src/intl/ja/page-community-events.json
wackerow Jan 15, 2026
c67d24e
update(i18n): src/intl/de/page-community-events.json
wackerow Jan 15, 2026
956126f
update(i18n): src/intl/ko/page-community-events.json
wackerow Jan 15, 2026
b97c6ac
update(i18n): src/intl/vi/page-community-events.json
wackerow Jan 15, 2026
6115632
update(i18n): src/intl/tr/page-community-events.json
wackerow Jan 15, 2026
1a1bd7b
update(i18n): src/intl/bn/page-community-events.json
wackerow Jan 15, 2026
9442330
update(i18n): src/intl/it/page-community-events.json
wackerow Jan 15, 2026
96ce773
update(i18n): src/intl/pl/page-community-events.json
wackerow Jan 15, 2026
a1792b7
update(i18n): src/intl/ur/page-community-events.json
wackerow Jan 15, 2026
d0e703f
update(i18n): src/intl/uk/page-community-events.json
wackerow Jan 15, 2026
74ec0e3
update(i18n): src/intl/ta/page-community-events.json
wackerow Jan 15, 2026
83b42b6
update(i18n): src/intl/te/page-community-events.json
wackerow Jan 15, 2026
9688f5f
update(i18n): src/intl/mr/page-community-events.json
wackerow Jan 15, 2026
4dd0b01
update(i18n): src/intl/sw/page-community-events.json
wackerow Jan 15, 2026
9392ad0
update(i18n): src/intl/zh-tw/page-community-events.json
wackerow Jan 15, 2026
d107c4b
update(i18n): src/intl/cs/page-community-events.json
wackerow Jan 15, 2026
f9d06d7
fix(i18n): preserve English brand names in translations
wackerow Jan 15, 2026
8bd4d5b
revert: regional tag
wackerow Jan 15, 2026
da5fdfb
patch: add search button, require input
wackerow Jan 15, 2026
6431d5e
Merge pull request #17020 from ethereum/events-revamp
wackerow Jan 15, 2026
a1fa898
Merge pull request #17089 from ethereum/i18n/import/2026-01-15T17-52-…
wackerow Jan 15, 2026
6f44105
Merge pull request #17078 from davidcardenasus/patch-3
wackerow Jan 15, 2026
4940f9a
Merge pull request #17085 from mdqst/patch-47
wackerow Jan 15, 2026
78bcf2a
10.21.0
wackerow Jan 15, 2026
b6b1fa2
Merge branch 'staging' into dev
wackerow Jan 15, 2026
7536356
i18n(zh): Crowdin translations
wackerow Jan 15, 2026
e55c7fd
i18n(es): Crowdin translations
wackerow Jan 15, 2026
0c886a9
i18n(hi): Crowdin translations
wackerow Jan 15, 2026
642d6e9
i18n(ar): Crowdin translations
wackerow Jan 15, 2026
9fec630
i18n(pt-br): Crowdin translations
wackerow Jan 15, 2026
34be984
i18n(fr): Crowdin translations
wackerow Jan 15, 2026
3f5d80b
i18n(id): Crowdin translations
wackerow Jan 15, 2026
b06a71b
i18n(ru): Crowdin translations
wackerow Jan 15, 2026
b652340
i18n(ja): Crowdin translations
wackerow Jan 15, 2026
745ce50
i18n(de): Crowdin translations
wackerow Jan 15, 2026
da93686
i18n(ko): Crowdin translations
wackerow Jan 15, 2026
9918424
i18n(vi): Crowdin translations
wackerow Jan 15, 2026
c5585e4
i18n(tr): Crowdin translations
wackerow Jan 15, 2026
571a7dc
i18n(bn): Crowdin translations
wackerow Jan 15, 2026
efd2f38
i18n(it): Crowdin translations
wackerow Jan 15, 2026
41488c5
i18n(pl): Crowdin translations
wackerow Jan 15, 2026
0c6eeb1
i18n(ur): Crowdin translations
wackerow Jan 15, 2026
058571d
i18n(uk): Crowdin translations
wackerow Jan 15, 2026
be4483d
i18n(ta): Crowdin translations
wackerow Jan 15, 2026
2bdb44c
i18n(te): Crowdin translations
wackerow Jan 15, 2026
a35ce37
i18n(mr): Crowdin translations
wackerow Jan 15, 2026
f4a166a
i18n(sw): Crowdin translations
wackerow Jan 15, 2026
56ad3ce
i18n(zh-tw): Crowdin translations
wackerow Jan 15, 2026
5f8795a
i18n(cs): Crowdin translations
wackerow Jan 15, 2026
9dcce57
fix(i18n): correct critical translation issues in 11 languages
wackerow Jan 16, 2026
4225aa3
Apply suggestions from code review
pettinarip Jan 16, 2026
1408158
Merge pull request #17093 from ethereum/i18n/import/2026-01-15T23-17-…
pettinarip Jan 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -13970,6 +13970,15 @@
"contributions": [
"content"
]
},
{
"login": "koyahness",
"name": "Koyah",
"avatar_url": "https://avatars.githubusercontent.com/u/210164754?v=4",
"profile": "https://github.com/koyahness",
"contributions": [
"content"
]
}
],
"contributorsPerLine": 7,
Expand Down
163 changes: 163 additions & 0 deletions .claude/commands/prepare-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
---
description: Prepare a release - version bump, branch sync, release notes cleanup, and deploy PR
allowed-tools: Bash, Read, Write, AskUserQuestion
argument-hints: --dry-run|--major|--minor|--patch
---

# Prepare Release Command

Automates the ethereum.org deployment workflow using `src/scripts/prepare-release.sh` for deterministic operations and Claude for intelligent tasks (version suggestion, release note cleanup).

## Arguments

Details for $ARGUMENTS

- `--dry-run` - Show what would happen without making any changes to remote
- `--major` - Major release (breaking/stack changes)
- `--minor` - Minor release (new features, content, translations)
- `--patch` - Patch release (bug fixes, typos, small updates)
- _(no flag)_ - Analyze changes and suggest version type

**Dry-run mode**: If `--dry-run` is in `$ARGUMENTS`, pass it as the first argument to ALL script commands. This shows what would happen without pushing to remote or creating PRs.

## Execution Flow

### Step 1: Pre-flight Checks

First, check if `--dry-run` is in `$ARGUMENTS`. If so, set `DRY_RUN_FLAG="--dry-run"`, otherwise set it to empty string.

Run the script to verify environment and sync branches:

```bash
./src/scripts/prepare-release.sh $DRY_RUN_FLAG preflight
```

This handles: `gh` authenticated, create worktree if not on `dev`, clean working tree, back-merge `master` → `staging` → `dev`, pull latest.

**Note**: The script can run from any branch. If not on `dev`, it creates a worktree at `/tmp/claude/worktrees/ethereum-org-dev` and performs all operations there.

If this fails, stop and report the error.

### Step 2: Determine Version Type

**If flag provided** (`--major`, `--minor`, `--patch`):
Extract from `$ARGUMENTS` and proceed to Step 3.

**If no flag provided**:
1. Fetch draft release: `./src/scripts/prepare-release.sh fetch-draft`
2. Analyze the changes:
- **Major**: Stack/framework changes, significant breaking updates (rare)
- **Minor**: New features, new content pages, significant translations, new components
- **Patch**: Bug fixes, typo corrections, small content updates, dependency bumps
3. Provide a ONE-LINE suggestion with reasoning
4. Use `AskUserQuestion` to confirm: "Proceed with **X** release?" with options: Yes / Change to major / Change to minor / Change to patch
5. Proceed only after confirmation

### Step 3: Version Bump

```bash
VERSION=$(./src/scripts/prepare-release.sh $DRY_RUN_FLAG version <type>)
```

### Step 4: Merge to Staging

```bash
./src/scripts/prepare-release.sh $DRY_RUN_FLAG merge-staging
```

### Step 5: Fetch Draft Release

```bash
DRAFT_JSON=$(./src/scripts/prepare-release.sh fetch-draft)
```

Parse the JSON to extract `tagName` (DRAFT_TAG) and `body`. If no draft exists, error out.

### Step 6: Clean Release Notes

The draft release body needs cleanup. Apply these filters:

**Remove from CHANGES sections** (lines matching these patterns):
- Author is `allcontributors` or `allcontributors[bot]` (these are just additions to our all-contributors list, not pertinent to actual changes)
- PR title contains "Release candidate v" (release management)
- PR title contains "Deploy v" (release management)
- PR title starts with "Staging -> dev" or "Staging -> Dev" (back-merge)
- PR title starts with "Master -> staging" or "Master -> Staging" (back-merge)
- PR title starts with "Back merge" (back-merge)
- PR title is just a version number like "v10.20.0" or "v11.0.0" (version bump commits)
- PR title starts with "Update translation contributors from Crowdin" (automated Crowdin)
- PR title starts with "Update translation progress from Crowdin" (automated Crowdin)

Note: Keep entries from other bots like `dependabot`, `claude[bot]`, `github-actions` - their PRs ARE meaningful changes (dependency updates, code changes, etc). We just don't thank them as human contributors.

**Remove from CONTRIBUTORS section** (the "Thank you @..." line):
These accounts should be filtered from the contributors list:
- `dependabot`
- `dependabot[bot]`
- `allcontributors`
- `allcontributors[bot]`
- `claude`
- `claude[bot]`
- `github-actions`
- `github-actions[bot]`
- `actions-user`

**Keep the structure intact**:
- Keep section headers (⚡️ Changes, 🌐 Translations, 🐛 Bug Fix, etc.)
- Keep the `***` separators
- Keep the 🦄 Contributors section (just filter the bot names from it)
- Remove empty sections if all entries were filtered out

Write cleaned body to temp file:
```bash
# Write the cleaned release notes to a temp file
cat << 'EOF' > /tmp/claude/release-notes.md
<cleaned_body>
EOF
```

### Step 7: Publish Release

```bash
RELEASE_URL=$(./src/scripts/prepare-release.sh $DRY_RUN_FLAG publish "$VERSION" "$DRAFT_TAG" /tmp/claude/release-notes.md)
```

### Step 8: Create Deploy PR

```bash
PR_URL=$(./src/scripts/prepare-release.sh $DRY_RUN_FLAG create-pr "$VERSION" /tmp/claude/release-notes.md)
```

### Step 9: Cleanup Worktree

If a worktree was created, clean it up:

```bash
./src/scripts/prepare-release.sh cleanup
```

### Step 10: Report Success

Output summary:
```
✅ Release prepared successfully!

Version: vX.X.X
Release: <release_url>
Deploy PR: <pr_url>

Next step: Review the preview build, then merge the PR when ready.
```

## Error Handling

- If any git operation fails, stop and report the error
- If `gh` commands fail, check authentication and permissions
- If no draft release exists, error with clear message
- If merge conflicts occur during back-merge, stop and instruct user to resolve manually

## Notes

- This command does NOT merge the deploy PR - that remains a manual step after QA
- The release can be edited after publishing if corrections are needed
- Always verify the cleaned release notes look correct before the PR is merged
80 changes: 80 additions & 0 deletions .claude/skills/data-layer/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
name: data-layer
description: This skill provides patterns for working with the data-layer module. Use when creating/editing files in src/data-layer/, src/lib/data/, or adding new data sources.
---

# Data Layer

## Architecture

```
src/data-layer/ # Isolated, framework-agnostic module
├── api/ # Fetch functions (one per data source)
├── index.ts # Getter functions (pure passthrough)
└── registry.ts # Task registry (hourly/daily)

src/lib/data/ # Next.js caching adapter
└── index.ts # Cached wrappers via createCachedGetter()
```

## Rules

### 1. Getters must be pure passthrough

In `src/data-layer/index.ts`, getter functions must only call `getData<T>(TASK_ID)` with no transformations:

```typescript
// Correct
export async function getEventsData(): Promise<EventItem[] | null> {
return getData<EventItem[]>(FETCH_EVENTS_TASK_ID)
}

// Wrong - no transformations in getters
export async function getEventsData(): Promise<EventItem[] | null> {
const data = await getData<EventItem[]>(FETCH_EVENTS_TASK_ID)
return data?.map((e) => ({ ...e, computed: derive(e) })) ?? null
}
```

All transformations belong in the fetch task (`src/data-layer/api/`), not in the getter.

### 2. Expose via lib/data for caching

When a data function needs caching/revalidation, add a cached wrapper in `src/lib/data/index.ts`:

```typescript
export const getEventsData = createCachedGetter(
dataLayer.getEventsData,
["events-data"],
CACHE_REVALIDATE_DAY // or CACHE_REVALIDATE_HOUR
)
```

## Adding a New Data Source

1. Create fetch function in `src/data-layer/api/fetchNewData.ts`:
```typescript
export const FETCH_NEW_DATA_TASK_ID = "fetch-new-data"

export async function fetchNewData(): Promise<YourDataType> {
// Fetch and transform data here
}
```

2. Add getter in `src/data-layer/index.ts`:
```typescript
export async function getNewData(): Promise<YourDataType | null> {
return getData<YourDataType>(FETCH_NEW_DATA_TASK_ID)
}
```

3. Register in `src/data-layer/registry.ts` (hourlyTasks or dailyTasks)

4. Add cached wrapper in `src/lib/data/index.ts`:
```typescript
export const getNewData = createCachedGetter(
dataLayer.getNewData,
["new-data"],
CACHE_REVALIDATE_HOUR
)
```
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,8 @@ USE_MOCK_DATA=true

# AWS SES Configuration for Enterprise Contact Form
# SES_ACCESS_KEY_ID=your_iam_access_key_id
# SES_SECRET_ACCESS_KEY=your_iam_secret_access_key
# SES_SECRET_ACCESS_KEY=your_iam_secret_access_key
# SES_REGION=us-east-2

# Supabase Events API (Geode Labs)
# SUPABASE_EVENTS_KEY=your-supabase-publishable-key
3 changes: 0 additions & 3 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,3 @@
"content 🖋️":
- src/intl/en/**
- public/content/**/*

"event 📅":
- src/data/community-events.json
2 changes: 1 addition & 1 deletion .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Run Claude PR Action
uses: anthropics/claude-code-action@beta
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
timeout_minutes: "60"
104 changes: 104 additions & 0 deletions .github/workflows/cleanup-netlify-previews.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: Cleanup Netlify Preview Deploys
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:

permissions:
contents: read
pull-requests: read

jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0

- name: Cleanup stale preview deploys
env:
NETLIFY_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Set to "false" to actually delete, "true" for dry-run
DRY_RUN: "false"
run: |
set -euo pipefail

echo "=== Netlify Preview Cleanup ==="
echo "DRY_RUN: $DRY_RUN"
echo ""

# 1. Fetch deploys with safety pagination
ALL_DEPLOYS="[]"
for PAGE in {1..100}; do
RESPONSE=$(curl -s -H "Authorization: Bearer $NETLIFY_TOKEN" \
"https://api.netlify.com/api/v1/sites/$NETLIFY_SITE_ID/deploys?per_page=100&page=$PAGE")

[[ $(echo "$RESPONSE" | jq 'length') -eq 0 ]] && break
ALL_DEPLOYS=$(echo "$ALL_DEPLOYS $RESPONSE" | jq -s 'add')
done

TOTAL_DEPLOYS=$(echo "$ALL_DEPLOYS" | jq 'length')
echo "Found $TOTAL_DEPLOYS total deploys"

# 2. Extract context and state data
PREVIEW_DEPLOYS=$(echo "$ALL_DEPLOYS" | jq '[.[] | select(.context == "deploy-preview" or .context == "branch-deploy")]')
PREVIEW_COUNT=$(echo "$PREVIEW_DEPLOYS" | jq 'length')
echo "Found $PREVIEW_COUNT preview/branch deploys"

OPEN_PRS=$(gh pr list --state open --json number --jq '.[].number')
REMOTE_BRANCHES=$(git branch -r | sed 's/origin\///' | tr -d ' ')

echo ""
echo "=== Processing deploys ==="

# 3. Process Deploys
echo "$PREVIEW_DEPLOYS" | jq -c '.[]' | while read -r DEPLOY; do
DEPLOY_ID=$(echo "$DEPLOY" | jq -r '.id')
BRANCH=$(echo "$DEPLOY" | jq -r '.branch')
CONTEXT=$(echo "$DEPLOY" | jq -r '.context')
CREATED=$(echo "$DEPLOY" | jq -r '.created_at')
URL=$(echo "$DEPLOY" | jq -r '.deploy_ssl_url // .deploy_url // "no-url"')

# Never touch production/staging branches
if [[ "$BRANCH" == "main" ]] || [[ "$BRANCH" == "master" ]] || [[ "$BRANCH" == "production" ]] || [[ "$BRANCH" == "staging" ]] || [[ "$BRANCH" == "dev" ]]; then
continue
fi

SHOULD_DELETE=false
REASON=""

if [[ "$CONTEXT" == "deploy-preview" ]]; then
PR_NUM=$(echo "$DEPLOY" | jq -r '.review_url // ""' | grep -oP 'pull/\K[0-9]+' || echo "")
if [[ -n "$PR_NUM" ]] && ! echo "$OPEN_PRS" | grep -Fxq "$PR_NUM"; then
SHOULD_DELETE=true
REASON="PR #$PR_NUM is closed/merged"
fi
else
if ! echo "$REMOTE_BRANCHES" | grep -Fxq "$BRANCH"; then
SHOULD_DELETE=true
REASON="Branch '$BRANCH' no longer exists"
fi
fi

if [ "$SHOULD_DELETE" = true ]; then
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY-RUN] Would delete: $DEPLOY_ID"
echo " Branch: $BRANCH"
echo " Reason: $REASON"
echo " Created: $CREATED"
echo " URL: $URL"
echo ""
else
echo "Deleting: $DEPLOY_ID ($BRANCH) - $REASON"
curl -s -X DELETE -H "Authorization: Bearer $NETLIFY_TOKEN" \
"https://api.netlify.com/api/v1/deploys/$DEPLOY_ID"
sleep 1
fi
fi
done

echo "=== Complete ==="
Loading
Loading