├── .gitattributes ├── .github ├── CODEOWNERS └── workflows │ ├── build.yml │ ├── npm-publish-canary.yml │ └── npm-publish.yml ├── .gitignore ├── .prettierrc ├── LICENSE ├── Makefile ├── README.md ├── package.json ├── renovate.json ├── website ├── .envrc ├── .gitignore ├── ambient.d.ts ├── flake.lock ├── flake.nix ├── next-env.d.ts ├── package.json ├── public │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── mstile-144x144.png │ ├── mstile-150x150.png │ ├── mstile-310x150.png │ ├── mstile-310x310.png │ ├── mstile-70x70.png │ ├── pattern.svg │ ├── screenshot-mutations.jpg │ ├── site.webmanifest │ ├── swiss-city-topo.json │ └── swiss-maps-icon.svg ├── src │ ├── components │ │ ├── Examples │ │ │ ├── Examples.tsx │ │ │ └── index.ts │ │ ├── Footer │ │ │ ├── Footer.tsx │ │ │ └── index.ts │ │ ├── Generator │ │ │ ├── Generator.tsx │ │ │ ├── context.ts │ │ │ ├── domain │ │ │ │ ├── deck-gl.ts │ │ │ │ └── dom.ts │ │ │ ├── index.ts │ │ │ └── internal │ │ │ │ ├── Export.tsx │ │ │ │ ├── Panel.tsx │ │ │ │ ├── Preview.tsx │ │ │ │ ├── ShapeOption.tsx │ │ │ │ ├── Stats.tsx │ │ │ │ └── WrappedPreview.tsx │ │ ├── GitHub │ │ │ ├── GitHub.tsx │ │ │ └── index.ts │ │ ├── HeadMeta │ │ │ ├── HeadMeta.tsx │ │ │ └── index.ts │ │ ├── Header │ │ │ ├── Header.tsx │ │ │ └── index.ts │ │ ├── Layout │ │ │ └── LayoutDefault.tsx │ │ └── Mutations │ │ │ ├── Map.tsx │ │ │ └── Minimap.tsx │ ├── domain │ │ ├── color-schema.ts │ │ ├── constants.ts │ │ ├── geodata.ts │ │ └── municipality-migrations.ts │ ├── icons │ │ ├── Facebook │ │ │ └── index.tsx │ │ ├── Instagram │ │ │ └── index.tsx │ │ ├── InteractiveThingsBrandmark │ │ │ └── index.tsx │ │ ├── Twitter │ │ │ └── index.tsx │ │ ├── descriptors.ts │ │ └── index.ts │ ├── pages │ │ ├── _app.tsx │ │ ├── _document.tsx │ │ ├── api │ │ │ ├── generate.ts │ │ │ ├── mutations.ts │ │ │ └── v0.ts │ │ ├── docs │ │ │ └── index.tsx │ │ ├── index.tsx │ │ └── mutations.tsx │ ├── shared.ts │ └── theme │ │ ├── colors.ts │ │ ├── index.ts │ │ ├── options.ts │ │ ├── provider.tsx │ │ └── shadows.ts ├── tsconfig.json └── yarn.lock └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | *.shp filter=lfs diff=lfs merge=lfs -text 2 | *.zip filter=lfs diff=lfs merge=lfs -text 3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @wereHamster 2 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build Files 2 | 3 | on: push 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 13 | - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 14 | with: 15 | node-version: 18 16 | 17 | - run: yarn --frozen-lockfile 18 | 19 | - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 20 | with: 21 | path: downloads 22 | key: downloads-${{ hashFiles('Makefile') }} 23 | restore-keys: | 24 | downloads- 25 | 26 | - run: make -j 27 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish-canary.yml: -------------------------------------------------------------------------------- 1 | name: Publish Canary to NPM 2 | 3 | on: 4 | push: 5 | tags: 6 | - v[0-9]+.[0-9]+.[0-9]+-canary.[0-9]+ 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | publish-npm: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | id-token: write 17 | 18 | steps: 19 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 20 | - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 21 | with: 22 | node-version: 18 23 | registry-url: "https://registry.npmjs.org" 24 | 25 | - run: yarn --frozen-lockfile 26 | 27 | - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 28 | with: 29 | path: downloads 30 | key: downloads-${{ hashFiles('Makefile') }} 31 | restore-keys: | 32 | downloads- 33 | 34 | - run: npm publish --tag canary 35 | env: 36 | NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} 37 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to NPM 2 | 3 | on: 4 | push: 5 | tags: 6 | - v[0-9]+.[0-9]+.[0-9]+ 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | publish-npm: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | id-token: write 17 | 18 | steps: 19 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 20 | - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 21 | with: 22 | node-version: 18 23 | registry-url: "https://registry.npmjs.org" 24 | 25 | - run: yarn --frozen-lockfile 26 | 27 | - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 28 | with: 29 | path: downloads 30 | key: downloads-${{ hashFiles('Makefile') }} 31 | restore-keys: | 32 | downloads- 33 | 34 | - run: npm publish 35 | env: 36 | NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .vscode 4 | /geo 5 | /tif 6 | /shp 7 | /topo 8 | /downloads 9 | /shapefile 10 | /topojson 11 | /build 12 | /svg 13 | /20*/ 14 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": false 4 | } 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 – present, Interactive Things GmbH 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the Interactive Things GmbH, nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Geodata 3 | # https://www.bfs.admin.ch/bfs/de/home/dienstleistungen/geostat/geodaten-bundesstatistik/administrative-grenzen/generalisierte-gemeindegrenzen.html 4 | # 5 | 6 | YEARS := 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2021-04 2021-07 2022 2022-05 2023 2024 2025 7 | SHAPES := country cantons districts municipalities lakes 8 | SHAPEFILE_EXT := shp dbf prj shx 9 | 10 | .PHONY: all topojson shapefile clean-generated 11 | 12 | all: shapefile topojson 13 | 14 | shapefile: \ 15 | $(foreach year,$(YEARS),$(year)/country.shp) \ 16 | $(foreach year,$(YEARS),$(year)/cantons.shp) \ 17 | $(foreach year,$(YEARS),$(year)/districts.shp) \ 18 | $(foreach year,$(YEARS),$(year)/municipalities.shp) \ 19 | $(foreach year,$(YEARS),$(year)/lakes.shp) 20 | 21 | topojson: \ 22 | $(foreach year,$(YEARS),$(year)/ch-combined.json) 23 | 24 | clean-generated: 25 | rm -rf 20*/ shapefile/ 26 | 27 | # --- 28 | 29 | # # SHAPEFILE_TARGETS := $(foreach ext,shp dbf prj shx,$(foreach type,countries,20%/$(type).$(ext))) 30 | # .PRECIOUS: $(SHAPEFILE_TARGETS) 31 | 32 | # shapefile-20%: $(SHAPEFILE_TARGETS) 33 | # @echo Shapefiles 20$* extracted 34 | 35 | SHAPEFILE_TARGETS := $(foreach shape,$(SHAPES),20%/$(shape).shp) 36 | 37 | 20%/ch-combined.json: $(SHAPEFILE_TARGETS) 38 | mkdir -p $(dir $@) 39 | yarn run mapshaper \ 40 | -i $^ combine-files string-fields=* \ 41 | -proj wgs84 \ 42 | -clean \ 43 | -simplify 50% \ 44 | -o format=topojson drop-table id-field=id $@ 45 | 46 | # Clean up country 47 | # - Unify ID ("CH") 48 | 20%/country.shp: $(foreach ext,$(SHAPEFILE_EXT),shapefile/20%/l.$(ext)) 49 | mkdir -p $(dir $@) 50 | yarn run mapshaper \ 51 | -i $< \ 52 | -clean \ 53 | -each 'id="CH"; name="Schweiz / Suisse / Svizzera"' \ 54 | -filter-fields id,name \ 55 | -o format=shapefile encoding=utf8 $@ 56 | 57 | # Clean up cantons 58 | # - Unify IDs 59 | 20%/cantons.shp: $(foreach ext,$(SHAPEFILE_EXT),shapefile/20%/k.$(ext)) 60 | mkdir -p $(dir $@) 61 | yarn run mapshaper \ 62 | -i $< \ 63 | -clean \ 64 | -each 'id=this.properties.KTNR || this.properties.KT; name=this.properties.KTNAME || this.properties.NAME' \ 65 | -filter-fields id,name \ 66 | -o format=shapefile encoding=utf8 $@ 67 | 68 | # Clean up cantons 69 | # - Unify IDs 70 | 20%/districts.shp: $(foreach ext,$(SHAPEFILE_EXT),shapefile/20%/b.$(ext)) 71 | mkdir -p $(dir $@) 72 | yarn run mapshaper \ 73 | -i $< \ 74 | -clean \ 75 | -each 'id=this.properties.BZNR || this.properties.BEZIRK; name=this.properties.BZNAME || this.properties.NAME; KTNR=this.properties.KTNR || this.properties.KT' \ 76 | -filter-fields id,name,KTNR \ 77 | -o format=shapefile encoding=utf8 $@ 78 | 79 | # Clean up municipalities 80 | # - Unify IDs 81 | # - Remove lakes (ID 9000+) and Liechtenstein municipalities from older shapefiles (ID 7000+) 82 | 20%/municipalities.shp: $(foreach ext,$(SHAPEFILE_EXT),shapefile/20%/g.$(ext)) 83 | mkdir -p $(dir $@) 84 | yarn run mapshaper \ 85 | -i $< $(if $(findstring 2017,$@),encoding=win1252,) \ 86 | -clean \ 87 | -each 'id=this.properties.GDENR || this.properties.GMDNR || this.properties.GMDE; name=this.properties.GMDNAME || this.properties.NAME; KTNR=this.properties.KTNR || this.properties.KT' \ 88 | -filter-fields id,name,KTNR \ 89 | -filter '+id < 7000' \ 90 | -o format=shapefile encoding=utf8 $@ 91 | 92 | # Clean up lakes 93 | # - Unify IDs 94 | # - Remove Lago di Como (9780) 95 | 20%/lakes.shp: $(foreach ext,$(SHAPEFILE_EXT),shapefile/20%/s.$(ext)) 96 | mkdir -p $(dir $@) 97 | yarn run mapshaper \ 98 | -i $< \ 99 | -clean \ 100 | -each 'id=this.properties.SEENR || this.properties.GMDNR || this.properties.GMDE; name=this.properties.SEENAME || this.properties.GMDNAME || this.properties.NAME' \ 101 | -filter-fields id,name \ 102 | -filter '+id !== 9780' \ 103 | -o format=shapefile encoding=utf8 $@ 104 | 105 | # Generate targets based on 106 | # - types (g=Gemeinde, k=Kanton, l=Landesgrenze, s=See), and 107 | # - extensions (shp, dbf, prj) 108 | # 109 | # Examples: 2020/g.shp, 2019/l.dbf, etc. 110 | 111 | define extract_from_archive 112 | ## 2010 – 2017 contain unique folder structures 113 | shapefile/2010/$(1).$(2): downloads/2010.zip 114 | @mkdir -p $$(dir $$@) 115 | unzip -p $$< g1g10_shp_121130/$$(subst l1,L1,$$(subst s1,S1,$$(subst k1,K1,$$(subst g1,G1,$$(subst b1,B1,G1$(1)10.$(2)))))) > $$@ 116 | shapefile/2011/$(1).$(2): downloads/2011.zip 117 | @mkdir -p $$(dir $$@) 118 | unzip -p $$< g1g11_shp_121130/$$(subst l1,L1,$$(subst s1,S1,$$(subst k1,K1,$$(subst g1,G1,$$(subst b1,B1,G1$(1)11.$(2)))))) > $$@ 119 | shapefile/2012/$(1).$(2): downloads/2012.zip 120 | @mkdir -p $$(dir $$@) 121 | unzip -p $$< g1g12_shp_121130/$$(subst l1,L1,$$(subst s1,S1,$$(subst k1,K1,$$(subst g1,G1,$$(subst b1,B1,G1$(1)12.$(2)))))) > $$@ 122 | shapefile/2013/$(1).$(2): downloads/2013.zip 123 | @mkdir -p $$(dir $$@) 124 | unzip -p $$< ggg_2013/shp/g1$(1)13.$(2) > $$@ 125 | shapefile/2014/$(1).$(2): downloads/2014.zip 126 | @mkdir -p $$(dir $$@) 127 | unzip -p $$< ggg_2014/shp/g1$(1)14.$(2) > $$@ 128 | shapefile/2015/$(1).$(2): downloads/2015.zip 129 | @mkdir -p $$(dir $$@) 130 | unzip -p $$< shp/g1$(1)15.$(2) > $$@ 131 | shapefile/2016/$(1).$(2): downloads/2016.zip 132 | @mkdir -p $$(dir $$@) 133 | unzip -p $$< ggg_2016/shp/g1$(1)16.$(2) > $$@ 134 | shapefile/2017/$(1).$(2): downloads/2017.zip 135 | @mkdir -p $$(dir $$@) 136 | unzip -p $$< ggg_2017/shp/LV95/g1$(1)17.$(2) > $$@ 137 | 138 | # Municipalities from 2021 are versioned by date in the file name 139 | shapefile/2021-07/g.$(2): downloads/2021.zip 140 | @mkdir -p $$(dir $$@) 141 | unzip -p $$< ggg_2021-LV95/shp/g1g21_01072021.$(2) > $$@ 142 | 143 | shapefile/2021-07/$(1).$(2): downloads/2021.zip 144 | @mkdir -p $$(dir $$@) 145 | unzip -p $$< ggg_2021-LV95/shp/g1$(1)21.$(2) > $$@ 146 | 147 | # There is no 01072021 prj file, so we use the one from 180042021 148 | shapefile/2021-07/g.prj: downloads/2021.zip 149 | @mkdir -p $$(dir $$@) 150 | unzip -p $$< ggg_2021-LV95/shp/g1g21_18042021.prj > $$@ 151 | 152 | shapefile/2021-04/g.$(2): downloads/2021.zip 153 | @mkdir -p $$(dir $$@) 154 | unzip -p $$< ggg_2021-LV95/shp/g1g21_18042021.$(2) > $$@ 155 | 156 | shapefile/2021-04/$(1).$(2): downloads/2021.zip 157 | @mkdir -p $$(dir $$@) 158 | unzip -p $$< ggg_2021-LV95/shp/g1$(1)21.$(2) > $$@ 159 | 160 | shapefile/2021/g.$(2): downloads/2021.zip 161 | @mkdir -p $$(dir $$@) 162 | unzip -p $$< ggg_2021-LV95/shp/g1g21_01012021.$(2) > $$@ 163 | 164 | shapefile/2021/$(1).$(2): downloads/2021.zip 165 | @mkdir -p $$(dir $$@) 166 | unzip -p $$< ggg_2021-LV95/shp/g1$(1)21.$(2) > $$@ 167 | 168 | shapefile/2022/$(1).$(2): downloads/2022.zip 169 | @mkdir -p $$(dir $$@) 170 | unzip -p $$< ag-b-00.03-875-gg22/ggg_2022_LV95/shp/g1$(1)22.$(2) > $$@ 171 | 172 | shapefile/2022-05/g.$(2): downloads/2022.zip 173 | @mkdir -p $$(dir $$@) 174 | unzip -p $$< ag-b-00.03-875-gg22/ggg_2022_LV95/shp/g1g22_20220501.$(2) > $$@ 175 | 176 | shapefile/2022-05/$(1).$(2): downloads/2022.zip 177 | @mkdir -p $$(dir $$@) 178 | unzip -p $$< ag-b-00.03-875-gg22/ggg_2022_LV95/shp/g1$(1)22.$(2) > $$@ 179 | 180 | shapefile/2023/$(1).$(2): downloads/2023.zip 181 | @mkdir -p $$(dir $$@) 182 | unzip -p $$< ag-b-00.03-875-gg23/ggg_2023_LV95/shp/g1$(1)23.$(2) > $$@ 183 | 184 | shapefile/2024/$(1).$(2): downloads/2024.zip 185 | @mkdir -p $$(dir $$@) 186 | unzip -p $$< ag-b-00.03-875-gg24/ggg_2024_LV95/shp/g1$(1)24.$(2) > $$@ 187 | 188 | shapefile/2025/$(1).$(2): downloads/2025.zip 189 | @mkdir -p $$(dir $$@) 190 | case $(1) in \ 191 | b) \ 192 | unzip -p $$< Districts_G1_20250101.$(2) > shapefile/2025/$(1).$(2) \ 193 | ;; \ 194 | g) \ 195 | unzip -p $$< Communes_G1_20250101.$(2) > shapefile/2025/$(1).$(2) \ 196 | ;; \ 197 | k) \ 198 | unzip -p $$< Cantons_G1_20250101.$(2) > shapefile/2025/$(1).$(2) \ 199 | ;; \ 200 | l) \ 201 | unzip -p $$< Country_G1_20250101.$(2) > shapefile/2025/$(1).$(2) \ 202 | ;; \ 203 | s) \ 204 | unzip -p $$< Lacs_G1_20250101.$(2) > shapefile/2025/$(1).$(2) \ 205 | ;; \ 206 | esac 207 | 208 | # Files from 2018 on seem to be consistently structured 209 | shapefile/20%/$(1).$(2): downloads/20%.zip 210 | @mkdir -p $$(dir $$@) 211 | unzip -p $$< ggg_20$$*-LV95/shp/g1$(1)$$*.$(2) > $$@ 212 | endef 213 | $(foreach type,g k l s b,$(foreach ext,$(SHAPEFILE_EXT),$(eval $(call extract_from_archive,$(type),$(ext))))) 214 | 215 | # rename = $(if $(findstring districts,$(1)),b,$(if $(findstring lakes,$(1)),s,$(if $(findstring municipalities,$(1)),g,$(if $(findstring cantons,$(1)),k,$(if $(findstring countries,$(1)),l,$(if $(findstring b,$(1)),districts,$(if $(findstring s,$(1)),lakes,$(if $(findstring g,$(1)),municipalities,$(if $(findstring k,$(1)),cantons,$(if $(findstring l,$(1)),countries,$(1))))))))))) 216 | 217 | # test-rename: 218 | # @echo 'l -> $(call rename,l)' 219 | # @echo 's -> $(call rename,s)' 220 | # @echo 'g -> $(call rename,g)' 221 | # @echo 'k -> $(call rename,k)' 222 | # @echo 'b -> $(call rename,b)' 223 | # @echo 'countries -> $(call rename,countries)' 224 | # @echo 'lakes -> $(call rename,lakes)' 225 | # @echo 'municipalities -> $(call rename,municipalities)' 226 | # @echo 'cantons -> $(call rename,cantons)' 227 | # @echo 'districts -> $(call rename,districts)' 228 | 229 | downloads/2025.zip: 230 | mkdir -p $(dir $@) 231 | curl -o downloads/2025.tmp.zip "https://dam-api.bfs.admin.ch/hub/api/dam/assets/34367751/master" 232 | unzip -p downloads/2025.tmp.zip "ag-b-00.03-875-gg25/Historized boundaries G1 20250101/Historized_boundaries_G1_20250101_2056.shp.zip" > $@ 233 | rm downloads/2025.tmp.zip 234 | 235 | downloads/2024.zip: 236 | mkdir -p $(dir $@) 237 | curl -o $@ "https://dam-api.bfs.admin.ch/hub/api/dam/assets/30487000/master" 238 | 239 | downloads/2023.zip: 240 | mkdir -p $(dir $@) 241 | curl -o $@ "https://dam-api.bfs.admin.ch/hub/api/dam/assets/24106754/master" 242 | 243 | downloads/2022.zip: 244 | mkdir -p $(dir $@) 245 | curl -o $@ "https://dam-api.bfs.admin.ch/hub/api/dam/assets/22484210/master" 246 | 247 | downloads/2021.zip: 248 | mkdir -p $(dir $@) 249 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/17964056/master" 250 | 251 | downloads/2020.zip: 252 | mkdir -p $(dir $@) 253 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/11947559/master" 254 | 255 | downloads/2019.zip: 256 | mkdir -p $(dir $@) 257 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/7566557/master" 258 | 259 | downloads/2018.zip: 260 | mkdir -p $(dir $@) 261 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/5247306/master" 262 | 263 | downloads/2016.zip: 264 | mkdir -p $(dir $@) 265 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/1902553/master" 266 | 267 | downloads/2017.zip: 268 | mkdir -p $(dir $@) 269 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/4342877/master" 270 | 271 | downloads/2015.zip: 272 | mkdir -p $(dir $@) 273 | curl -o downloads/2015.tmp.zip "https://www.bfs.admin.ch/bfsstatic/dam/assets/330759/master" 274 | unzip -p downloads/2015.tmp.zip GGG_15_V161025.zip > $@ 275 | rm downloads/2015.tmp.zip 276 | 277 | downloads/2014.zip: 278 | mkdir -p $(dir $@) 279 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/328824/master" 280 | 281 | downloads/2013.zip: 282 | mkdir -p $(dir $@) 283 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/282011/master" 284 | 285 | downloads/2012.zip: 286 | mkdir -p $(dir $@) 287 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/301391/master" 288 | 289 | downloads/2011.zip: 290 | mkdir -p $(dir $@) 291 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/301387/master" 292 | 293 | downloads/2010.zip: 294 | mkdir -p $(dir $@) 295 | curl -o $@ "https://www.bfs.admin.ch/bfsstatic/dam/assets/301383/master" 296 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![swiss-maps on npm](https://shields.io/npm/v/swiss-maps)](https://www.npmjs.com/package/swiss-maps) 2 | 3 | > This is the documentation for the swiss-maps npm package and website v4. 4 | > For the previous Makefile and instructions, please check the [legacy branch](https://github.com/interactivethings/swiss-maps/tree/legacy). 5 | 6 | # Swiss Maps 7 | 8 | This repository provides a mechanism to generate [TopoJSON](https://github.com/mbostock/topojson) from publicly available [swisstopo](https://www.swisstopo.admin.ch/) geodata. 9 | 10 | The geodata is based on the generalized from the [FSO](https://www.bfs.admin.ch/bfs/en/home/services/geostat/swiss-federal-statistics-geodata/administrative-boundaries/generalized-boundaries-local-regional-authorities.html). 11 | 12 | The `Makefile` cleans the source data further, so the features are as consistent as possible across different years and the properties are consistently named. 13 | 14 | For convenience, the generated files are published on [npm](https://www.npmjs.com/package/swiss-maps) 15 | 16 | ## Getting Started 17 | 18 | All Shapefiles and TopoJSON files are cleaned and pre-packaged in this package. 19 | 20 | You can install it locally using npm: 21 | 22 | ```sh 23 | npm i swiss-maps 24 | ``` 25 | 26 | You can read the files from the installed package directory, which is structured like this: 27 | 28 | ``` 29 | - node_modules/ 30 | - swiss-maps/ 31 | - 2010/ 32 | - cantons.{dbf,prj,shp,shx} 33 | - country.{dbf,prj,shp,shx} 34 | - districts.{dbf,prj,shp,shx} 35 | - lakes.{dbf,prj,shp,shx} 36 | - municipalities.{dbf,prj,shp,shx} 37 | - ch-combined.json (TopoJSON) 38 | - 2011/ 39 | ... 40 | - 2021/ 41 | ``` 42 | 43 | The TopoJSON file combines all layers into one file. Separate TopoJSON files for single layers will be added in the future. 44 | 45 | ## Use the TopoJson files in your web application 46 | 47 | ### Load from Unpkg.com 48 | 49 | If you don't want to install anything and just want to load the file, you can `fetch` it from https://unpkg.com (or any other npm registry CDN). 50 | 51 | ```js 52 | import * as topojson from "topojson-client"; 53 | 54 | const res = await fetch(`https://unpkg.com/swiss-maps@4/2021/ch-combined.json`); 55 | const topo = await res.json(); 56 | 57 | const municipalities = topojson.feature(topo, topo.objects.municipalities); 58 | // Render the municipalities ... 59 | ``` 60 | 61 | ### Bundled app (e.g. Next.js) 62 | 63 | If you're using a bundler that can resolve locally installed npm packages, you can add the `swiss-maps` npm package to your project. 64 | 65 | ```sh 66 | npm i swiss-maps 67 | ``` 68 | 69 | ```js 70 | import * as topojson from "topojson-client"; 71 | 72 | const topo = await import(`swiss-maps/2021/ch-combined.json`); 73 | 74 | const municipalities = topojson.feature(topo, topo.objects.municipalities); 75 | 76 | // Render the municipalities ... 77 | ``` 78 | 79 | ## License 80 | 81 | The code in this repository is licensed under BSD-3-Clause. 82 | 83 | The geodata is published under a non-commercial license and needs to be attributed with the source "Bundesamt für Statistik (BFS), GEOSTAT". 84 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "swiss-maps", 3 | "version": "4.6.1", 4 | "description": "Swiss geodata as TopoJSON.", 5 | "license": "bsd-3-clause", 6 | "keywords": [ 7 | "topojson", 8 | "geojson", 9 | "shapefile" 10 | ], 11 | "author": { 12 | "name": "Interactive Things", 13 | "url": "http://interactivethings.com/" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/interactivethings/swiss-maps.git" 18 | }, 19 | "scripts": { 20 | "preversion": "make", 21 | "postversion": "git push --follow-tags", 22 | "prepublishOnly": "make" 23 | }, 24 | "files": [ 25 | "README.md", 26 | "LICENSE", 27 | "20*/*" 28 | ], 29 | "dependencies": {}, 30 | "devDependencies": { 31 | "mapshaper": "^0.6.102" 32 | }, 33 | "publishConfig": { 34 | "access": "public", 35 | "provenance": true 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:recommended"], 4 | "rangeStrategy": "bump", 5 | "prHourlyLimit": 0, 6 | "postUpdateOptions": ["yarnDedupeHighest"], 7 | "dependencyDashboardApproval": true, 8 | "packageRules": [ 9 | { 10 | "addLabels": ["dependencies"], 11 | "matchPackageNames": ["*"] 12 | }, 13 | { 14 | "matchPackageNames": ["mapshaper"], 15 | "groupName": "Mapshaper" 16 | }, 17 | { 18 | "extends": ["monorepo:react"], 19 | "groupName": "React" 20 | }, 21 | { 22 | "extends": ["monorepo:nextjs"], 23 | "groupName": "Next.js" 24 | }, 25 | { 26 | "matchPackageNames": ["immer", "use-immer"], 27 | "groupName": "Immer" 28 | }, 29 | { 30 | "groupName": "deck.gl", 31 | "matchPackageNames": ["/^@deck.gl//"] 32 | }, 33 | { 34 | "automerge": true, 35 | "matchPackageNames": ["/^@types//", "/^typescript$/"] 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /website/.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | .direnv/ 2 | .next/ 3 | node_modules/ 4 | 5 | public/swiss-maps/ 6 | 7 | tsconfig.tsbuildinfo 8 | -------------------------------------------------------------------------------- /website/ambient.d.ts: -------------------------------------------------------------------------------- 1 | declare type $FixMe = any; 2 | 3 | declare module "mapshaper"; 4 | 5 | declare module "@deck.gl/core" { 6 | export class MapController {} 7 | export class FlyToInterpolator {} 8 | export class WebMercatorViewport { 9 | constructor(viewState: $FixMe); 10 | project(lonlat: [number, number]): [number, number]; 11 | unproject(xy: [number, number]): [number, number]; 12 | fitBounds( 13 | bbox: [[number, number], [number, number]], 14 | options?: { 15 | padding?: number; 16 | offset?: [number, number]; 17 | } 18 | ): { 19 | zoom: number; 20 | longitude: number; 21 | latitude: number; 22 | }; 23 | } 24 | } 25 | 26 | declare module "@deck.gl/layers" { 27 | export const GeoJsonLayer: $FixMe; 28 | export const LineLayer: $FixMe; 29 | export const PathLayer: $FixMe; 30 | export const ScatterplotLayer: $FixMe; 31 | } 32 | 33 | declare module "@deck.gl/react" { 34 | export const DeckGL: $FixMe; 35 | export default DeckGL; 36 | } 37 | -------------------------------------------------------------------------------- /website/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1731533236, 9 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "nixpkgs": { 22 | "locked": { 23 | "lastModified": 1736134818, 24 | "narHash": "sha256-30sOEZ8CFK2nTTMdkhaNrfVlIi3rWTNV0Z5z+NmpFNI=", 25 | "owner": "nixos", 26 | "repo": "nixpkgs", 27 | "rev": "3df3c47c19dc90fec35359e89ffb52b34d2b0e94", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "owner": "NixOS", 32 | "ref": "nixpkgs-unstable", 33 | "repo": "nixpkgs", 34 | "type": "github" 35 | } 36 | }, 37 | "root": { 38 | "inputs": { 39 | "flake-utils": "flake-utils", 40 | "nixpkgs": "nixpkgs" 41 | } 42 | }, 43 | "systems": { 44 | "locked": { 45 | "lastModified": 1681028828, 46 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 47 | "owner": "nix-systems", 48 | "repo": "default", 49 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 50 | "type": "github" 51 | }, 52 | "original": { 53 | "owner": "nix-systems", 54 | "repo": "default", 55 | "type": "github" 56 | } 57 | } 58 | }, 59 | "root": "root", 60 | "version": 7 61 | } 62 | -------------------------------------------------------------------------------- /website/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | flake-utils.url = "github:numtide/flake-utils"; 5 | }; 6 | 7 | outputs = { self, nixpkgs, flake-utils }: 8 | flake-utils.lib.eachDefaultSystem 9 | (system: 10 | let 11 | pkgs = import nixpkgs { 12 | inherit system; 13 | }; 14 | 15 | in { 16 | devShells.default = pkgs.mkShell { 17 | buildInputs = [ 18 | pkgs.nodejs 19 | pkgs.yarn 20 | ]; 21 | }; 22 | } 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /website/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "website", 4 | "scripts": { 5 | "dev": "next dev", 6 | "build": "cp -r node_modules/swiss-maps public/ && next build" 7 | }, 8 | "dependencies": { 9 | "@deck.gl/core": "^9.1.11", 10 | "@deck.gl/layers": "^9.1.11", 11 | "@deck.gl/react": "^9.1.11", 12 | "@deck.gl/widgets": "^9.1.11", 13 | "@emotion/cache": "^11.14.0", 14 | "@emotion/react": "^11.14.0", 15 | "@emotion/server": "^11.11.0", 16 | "@emotion/styled": "^11.14.0", 17 | "@mui/material": "^7.0.2", 18 | "@mui/material-nextjs": "^7.0.2", 19 | "@tanstack/react-query": "^5.74.7", 20 | "@turf/turf": "^7.2.0", 21 | "@types/cors": "^2.8.17", 22 | "@types/d3": "^7.4.3", 23 | "@types/jsdom": "^21.1.7", 24 | "@types/node": "^22.14.1", 25 | "@types/react": "^19.1.2", 26 | "@types/topojson": "^3.2.6", 27 | "bezier-easing": "^2.1.0", 28 | "clsx": "^2.1.1", 29 | "cors": "^2.8.5", 30 | "d3": "^7.9.0", 31 | "fp-ts": "^2.16.10", 32 | "immer": "^10.1.1", 33 | "io-ts": "^2.2.22", 34 | "jsdom": "^26.1.0", 35 | "jss": "^10.10.0", 36 | "mapshaper": "^0.6.102", 37 | "next": "^15.3.1", 38 | "react": "^19.1.0", 39 | "react-dom": "^19.1.0", 40 | "react-feather": "^2.0.10", 41 | "swiss-maps": "^4.6.1", 42 | "typescript": "^5.8.3", 43 | "use-immer": "^0.11.0", 44 | "zod": "^3.24.3" 45 | }, 46 | "devDependencies": {} 47 | } 48 | -------------------------------------------------------------------------------- /website/public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /website/public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /website/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/apple-touch-icon.png -------------------------------------------------------------------------------- /website/public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /website/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/favicon-16x16.png -------------------------------------------------------------------------------- /website/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/favicon-32x32.png -------------------------------------------------------------------------------- /website/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/favicon.ico -------------------------------------------------------------------------------- /website/public/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/mstile-144x144.png -------------------------------------------------------------------------------- /website/public/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/mstile-150x150.png -------------------------------------------------------------------------------- /website/public/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/mstile-310x150.png -------------------------------------------------------------------------------- /website/public/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/mstile-310x310.png -------------------------------------------------------------------------------- /website/public/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/mstile-70x70.png -------------------------------------------------------------------------------- /website/public/screenshot-mutations.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/interactivethings/swiss-maps/3c0e9bded3473bcd95afd29d35254dc8590a8d8d/website/public/screenshot-mutations.jpg -------------------------------------------------------------------------------- /website/public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /website/public/swiss-city-topo.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Topology", 3 | "arcs": [], 4 | "objects": { 5 | "swiss-city": { 6 | "type": "GeometryCollection", 7 | "geometries": [ 8 | { 9 | "type": "Point", 10 | "coordinates": [ 11 | 7.3449995, 12 | 47.3699971 13 | ], 14 | "properties": { 15 | "NAME": "Delémont", 16 | "SOV0NAME": "Switzerland" 17 | } 18 | }, 19 | { 20 | "type": "Point", 21 | "coordinates": [ 22 | 6.9229986, 23 | 46.9989991 24 | ], 25 | "properties": { 26 | "NAME": "Neuchâtel", 27 | "SOV0NAME": "Switzerland" 28 | } 29 | }, 30 | { 31 | "type": "Point", 32 | "coordinates": [ 33 | 8.0340036, 34 | 47.3900041 35 | ], 36 | "properties": { 37 | "NAME": "Aarau", 38 | "SOV0NAME": "Switzerland" 39 | } 40 | }, 41 | { 42 | "type": "Point", 43 | "coordinates": [ 44 | 8.3833025, 45 | 46.9500031 46 | ], 47 | "properties": { 48 | "NAME": "Stans", 49 | "SOV0NAME": "Switzerland" 50 | } 51 | }, 52 | { 53 | "type": "Point", 54 | "coordinates": [ 55 | 7.3539995, 56 | 46.239003 57 | ], 58 | "properties": { 59 | "NAME": "Sion", 60 | "SOV0NAME": "Switzerland" 61 | } 62 | }, 63 | { 64 | "type": "Point", 65 | "coordinates": [ 66 | 9.2833025, 67 | 47.383299 68 | ], 69 | "properties": { 70 | "NAME": "Herisau", 71 | "SOV0NAME": "Switzerland" 72 | } 73 | }, 74 | { 75 | "type": "Point", 76 | "coordinates": [ 77 | 9.3619986, 78 | 47.4229981 79 | ], 80 | "properties": { 81 | "NAME": "Saint Gallen", 82 | "SOV0NAME": "Switzerland" 83 | } 84 | }, 85 | { 86 | "type": "Point", 87 | "coordinates": [ 88 | 9.0199986, 89 | 46.1970001 90 | ], 91 | "properties": { 92 | "NAME": "Bellinzona", 93 | "SOV0NAME": "Switzerland" 94 | } 95 | }, 96 | { 97 | "type": "Point", 98 | "coordinates": [ 99 | 9.0666996, 100 | 47.050002 101 | ], 102 | "properties": { 103 | "NAME": "Glarus", 104 | "SOV0NAME": "Switzerland" 105 | } 106 | }, 107 | { 108 | "type": "Point", 109 | "coordinates": [ 110 | 8.6329985, 111 | 47.7060031 112 | ], 113 | "properties": { 114 | "NAME": "Schaffhausen", 115 | "SOV0NAME": "Switzerland" 116 | } 117 | }, 118 | { 119 | "type": "Point", 120 | "coordinates": [ 121 | 8.6480016, 122 | 47.019996 123 | ], 124 | "properties": { 125 | "NAME": "Schwyz", 126 | "SOV0NAME": "Switzerland" 127 | } 128 | }, 129 | { 130 | "type": "Point", 131 | "coordinates": [ 132 | 8.904888469310368, 133 | 47.55261942265613 134 | ], 135 | "properties": { 136 | "NAME": "Frauenfeld", 137 | "SOV0NAME": "Switzerland" 138 | } 139 | }, 140 | { 141 | "type": "Point", 142 | "coordinates": [ 143 | 8.6380026, 144 | 46.8790021 145 | ], 146 | "properties": { 147 | "NAME": "Altdorf", 148 | "SOV0NAME": "Switzerland" 149 | } 150 | }, 151 | { 152 | "type": "Point", 153 | "coordinates": [ 154 | 8.4870006, 155 | 47.178999 156 | ], 157 | "properties": { 158 | "NAME": "Zug", 159 | "SOV0NAME": "Switzerland" 160 | } 161 | }, 162 | { 163 | "type": "Point", 164 | "coordinates": [ 165 | 7.1499965, 166 | 46.8000001 167 | ], 168 | "properties": { 169 | "NAME": "Fribourg", 170 | "SOV0NAME": "Switzerland" 171 | } 172 | }, 173 | { 174 | "type": "Point", 175 | "coordinates": [ 176 | 7.7370035, 177 | 47.4830011 178 | ], 179 | "properties": { 180 | "NAME": "Liestal", 181 | "SOV0NAME": "Switzerland" 182 | } 183 | }, 184 | { 185 | "type": "Point", 186 | "coordinates": [ 187 | 7.5369966, 188 | 47.2120021 189 | ], 190 | "properties": { 191 | "NAME": "Solothurn", 192 | "SOV0NAME": "Switzerland" 193 | } 194 | }, 195 | { 196 | "type": "Point", 197 | "coordinates": [ 198 | 8.2430015, 199 | 46.899 200 | ], 201 | "properties": { 202 | "NAME": "Sarnen", 203 | "SOV0NAME": "Switzerland" 204 | } 205 | }, 206 | { 207 | "type": "Point", 208 | "coordinates": [ 209 | 9.4167005, 210 | 47.3333041 211 | ], 212 | "properties": { 213 | "NAME": "Appenzell", 214 | "SOV0NAME": "Switzerland" 215 | } 216 | }, 217 | { 218 | "type": "Point", 219 | "coordinates": [ 220 | 9.5000297, 221 | 46.8500202 222 | ], 223 | "properties": { 224 | "NAME": "Chur", 225 | "SOV0NAME": "Switzerland" 226 | } 227 | }, 228 | { 229 | "type": "Point", 230 | "coordinates": [ 231 | 7.2500378, 232 | 47.16659 233 | ], 234 | "properties": { 235 | "NAME": "Biel", 236 | "SOV0NAME": "Switzerland" 237 | } 238 | }, 239 | { 240 | "type": "Point", 241 | "coordinates": [ 242 | 8.2800008, 243 | 47.0504214 244 | ], 245 | "properties": { 246 | "NAME": "Luzern", 247 | "SOV0NAME": "Switzerland" 248 | } 249 | }, 250 | { 251 | "type": "Point", 252 | "coordinates": [ 253 | 8.9666772, 254 | 46.0003821 255 | ], 256 | "properties": { 257 | "NAME": "Lugano", 258 | "SOV0NAME": "Switzerland" 259 | } 260 | }, 261 | { 262 | "type": "Point", 263 | "coordinates": [ 264 | 6.6500227, 265 | 46.5304273 266 | ], 267 | "properties": { 268 | "NAME": "Lausanne", 269 | "SOV0NAME": "Switzerland" 270 | } 271 | }, 272 | { 273 | "type": "Point", 274 | "coordinates": [ 275 | 7.590017, 276 | 47.580389 277 | ], 278 | "properties": { 279 | "NAME": "Basel", 280 | "SOV0NAME": "Switzerland" 281 | } 282 | }, 283 | { 284 | "type": "Point", 285 | "coordinates": [ 286 | 7.4669755, 287 | 46.9166828 288 | ], 289 | "properties": { 290 | "NAME": "Bern", 291 | "SOV0NAME": "Switzerland" 292 | } 293 | }, 294 | { 295 | "type": "Point", 296 | "coordinates": [ 297 | 8.5480643, 298 | 47.3819337 299 | ], 300 | "properties": { 301 | "NAME": "Zürich", 302 | "SOV0NAME": "Switzerland" 303 | } 304 | }, 305 | { 306 | "type": "Point", 307 | "coordinates": [ 308 | 6.140028, 309 | 46.2100075 310 | ], 311 | "properties": { 312 | "NAME": "Geneva", 313 | "SOV0NAME": "Switzerland" 314 | } 315 | } 316 | ] 317 | } 318 | } 319 | } -------------------------------------------------------------------------------- /website/public/swiss-maps-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /website/src/components/Examples/Examples.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as MUI from "@mui/material"; 3 | import { styled } from "@mui/material/styles"; 4 | 5 | /** 6 | * The underlying DOM element which is rendered by this component. 7 | */ 8 | const Root = styled("div", { 9 | name: "SwissMaps-Examples", 10 | slot: "root", 11 | })(({ theme }) => ({ 12 | padding: theme.spacing(15, 3), 13 | })); 14 | 15 | interface Props extends React.ComponentPropsWithoutRef {} 16 | 17 | function Examples(props: Props, ref: any) { 18 | const { ...rest } = props; 19 | 20 | return ( 21 | 22 |
23 | 24 | Examples 25 | 26 | 27 | Made with Swiss Maps 28 | 29 |
30 | 31 | 32 | 33 | 34 |