{"id":28576961,"url":"https://github.com/maptiler/foss4g-workshop","last_synced_at":"2026-03-03T16:40:48.763Z","repository":{"id":46809720,"uuid":"408360549","full_name":"maptiler/foss4g-workshop","owner":"maptiler","description":"Repository for From your data to vector tiles in your web\u0026mobile app workshop at FOSS4G 2021, Buenos Aires","archived":false,"fork":false,"pushed_at":"2021-11-28T14:30:10.000Z","size":8641,"stargazers_count":10,"open_issues_count":0,"forks_count":6,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-03-26T15:22:49.188Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maptiler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-09-20T08:12:57.000Z","updated_at":"2024-02-26T03:18:38.000Z","dependencies_parsed_at":"2022-07-26T13:17:08.378Z","dependency_job_id":null,"html_url":"https://github.com/maptiler/foss4g-workshop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maptiler%2Ffoss4g-workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maptiler%2Ffoss4g-workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maptiler%2Ffoss4g-workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maptiler%2Ffoss4g-workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maptiler","download_url":"https://codeload.github.com/maptiler/foss4g-workshop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maptiler%2Ffoss4g-workshop/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259172986,"owners_count":22816560,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-11T00:08:26.233Z","updated_at":"2026-03-03T16:40:43.737Z","avatar_url":"https://github.com/maptiler.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# foss4g-workshop\nRepository for From your data to vector tiles in your web\u0026amp;mobile app workshop at FOSS4G 2021, Buenos Aires\n\nThis README will guide you through the workshop step by step.\nThe goal of the workshop is to have a web application with \nmap showing cycleways in the center of Buenos Aires. There will\nbe also POIs - bike shops and bike sharing stations - with pop-ups\ndisplaying some additional information about the POI. The map will be\nin a theme of FOSS4G 2021.\n\n## Intro - setup tools\n\n[![From your data to vector tiles in web \u0026 mobile apps | FOSS4G 2021 Workshop #0 Intro](https://user-images.githubusercontent.com/59284/143770901-a5e9aeeb-17ec-47e9-a119-9f51948ed6df.jpeg)](https://www.youtube.com/watch?v=PANgq4Xgyy8\u0026list=PLGHe6Moaz52Mcq4BC9vczIIizNzwIYocv\u0026index=3\u0026ab_channel=MapTiler)\n\n\n- Docker, docker-compose\n  - Installation guide\n    - https://docs.docker.com/get-docker/\n    - https://docs.docker.com/compose/install/ \n  - Pull Docker images\n    ```\n    docker pull openmaptiles/postgis:5.3\n    docker pull openmaptiles/import-data:5.3\n    docker pull openmaptiles/openmaptiles-tools:5.3\n    ```\n\n- QGIS\n  - Version 3.16 or later \n  - Installation guide at https://qgis.org/en/site/forusers/download.html\n  - Including `qgis-grass-plugin`\n\n\n- IDE\n  - gedit, notepad, Sublime...\n\n\n- MapTiler Cloud\n  - https://cloud.maptiler.com\n  - Sign-in with Google Account\n\n\n- StackBlitz\n  - https://stackblitz.com \n  - Sign-in with Google Account\n\n\n- CloudShell\n  - https://cloud.google.com/\n  - Sign-in with Google Account\n\n## Block 1 - Extract data from OpenStreetMap\n\n[![Extract data from OpenStreetMap | FOSS4G 2021 Workshop Block #1](https://user-images.githubusercontent.com/59284/143771548-76a9de21-4aec-44fe-9757-576aaee63a13.jpeg)](https://www.youtube.com/watch?v=mx9l_yn8Dc0\u0026list=PLGHe6Moaz52Mcq4BC9vczIIizNzwIYocv\u0026index=2\u0026ab_channel=MapTiler)\n\n\n### Project preparation\n**Download 3.12.2 release**\n```\nmkdir foss4g\nwget https://github.com/openmaptiles/openmaptiles/archive/refs/tags/v3.12.2.zip\nunzip v3.12.2\nmv openmaptiles-3.12.2 openmaptiles\n```\n\n**Download Buenos Aires city from OSM**\n```\nmake download-osmfr area=south-america/argentina/buenos_aires_city\n```\n### Creating extra layer **cycleway**\n\n- Create folder `cycleway` in `layers`\n\n- Create empty files:\n  - `mapping.yaml`\n    - used by imposm (used by import-osm)\n  - `cycleway.yaml`\n    - used by OMT-T\n  - `cycleway_merge.sql`\n    - data pre-processing (during import-sql)\n  - `cycleway.sql`\n    - used by import-sql\n\n\n\n### code for files\n- [code for mapping.yaml](./block-1/cycleway/mapping.yaml)\n- [code for cycleway.yaml](./block-1/cycleway/cycleway.yaml)\n  - `id` - id of layer used in style\n  - `buffer_size` - buffer around layer for rendering purposes - should be bigger for layers with labels\n  - `fields` - attributes definition\n  - `datasource` - definition of the layer sql function\n  - `schema` - additional sql files that should be run\n- [code for cycleway_merge.sql](./block-1/cycleway/cycleway_merge.sql)\n- [code for cycleway.sql](./block-1/cycleway/cycleway.sql)\n\n### project modification\n\n**Modification of .env file**\n - `BORDERS_CLEANUP=true`\n - `MAX_ZOOM=14`\n\n**Add cycleway.yaml into openmaptiles.yaml**\n  - `layers/cycleway/cycleway.yaml`\n  - `center: [0, 0, 10]`\n  - `id: foss4g`\n\n**modification of docker-compose.yml - postgres ports**\n  - `\"5432:5432\"`\n\n### import OSM into database\n```\nmake clean\nmake\n\nmake import-borders\nmake import-data\n\nmake import-osm\nmake import-wikidata\n```\n \n\n## Block 2 - Add own data, analyse in QGIS \u0026 PostGIS\n\n[![Add own data, analyse in QGIS \u0026 PostGIS | FOSS4G 2021 Workshop Block #2](https://user-images.githubusercontent.com/59284/143771967-81a31851-0256-4e29-ae2b-3d3ffa6239cb.jpeg)](https://www.youtube.com/watch?v=3xpTBJAL8nc\u0026list=PLGHe6Moaz52Mcq4BC9vczIIizNzwIYocv\u0026index=3\u0026ab_channel=MapTiler)\n\n### 1. Add PostGIS connection to QGIS.\n\nGo to Browser/PostGIS/New Connection…\n- Name: osm_buenos_aires\n- Host: localhost\n- Port: 5432\n- Database: openmaptiles\n- User: openmaptiles\n- Password: openmaptiles\n\nCheck you can see added `osm_cycleway_linestring` table. Go to Browser/PostGIS/osm_buenos_aires/public/osm_cycleway_linestring and\ndouble-click on it. Cycleways should be added to map canvas.\n\n### 2. Add basemap for context via MapTiler plugin\n\n1. Go to Plugins/Manage and Install plugins.../All and search for `MapTiler`\n2. Right-click on MapTiler in Browser and add API key `\u003cyour-API-key\u003e`\n   \u003e :warning: **Expired API key**: This API key was generated just for workshop purpose. Get your own at https://cloud.maptiler.com\n3Add Streets map\n\n\n### 3. Analyse bike shops (geojson) in QGIS\n\n#### Add GeoJSON to QGIS\n\n1. Download GeoJSON from https://dev.maptiler.download/foss4g/bicicleterias/bicicleterias-de-la-ciudad.geojson\n2. Add GeoJSON to QGIS (drag and drop) \n3. Reproject data from WGS84 (EPSG:4326) to Pseudo-Mercator (EPSG:3857).\n   1. Go to Processing toolbox/Vector general/Reproject layer\n   2. Choose Input layer: `bicicleterias-de-la-ciudad bicicleterias_WGS [EPSG:4326]`\n   3. Choose Target CRS: `EPSG:3857 - WGS 84/Pseudo-Mercator`\n   4. Choose `[Create temporary layer]`\n   5. Run\n\n#### Add new attribute field\n1. Open attribute table\n2. Toggle editing\n3. Add New field\n   1. Name: distance\n   2. Type: Integer\n4. Save edits\n\n#### Distance analysis\nGo to Processing toolbox/GRASS/vector/v.distance \n - from: Reprojected\n - to: osm_cycleway_linestring\n - upload: dist\n - column for upload: distance\n - Save to temporary file Nearest\n\n#### Export \nRight-click on Nearest/Make Permanent\n - Format: GeoJSON\n - File name: `openmaptiles/data/bike_shops_w_distance.geojson`.\n\n### 4. Import bike shops (geojson) to PostGIS\n\nProcessed GeoJSON available for download at: \nhttps://dev.maptiler.download/foss4g/bike_shops_w_distance/bike_shops_w_distance.geojson\n\nUse `import-data` docker image to import the processed GeoJSON `bike_shops_w_distance.geojson into` \nPostGIS table `ba_bike_shops`.\n\n```\ncd openmaptiles\ndocker-compose run --rm -v $PWD:/omt import-data /bin/sh\nogr2ogr --version\nogr2ogr -f \"PostgreSQL\" PG:\"dbname=openmaptiles\" /omt/data/bike_shops_w_distance.geojson -nln ba_bike_shops\nexit\n```\n\nYou should be able to see the table `ba_bike_shops` in QGIS now.\n\n### 5. Import Shapefile to PostGIS\n1. Download zip file from https://dev.maptiler.download/foss4g/estaciones/estaciones-de-bicicletas-zip.zip\n2. Extract zip file into `openmaptiles/data`.\n3. Import shapefile to PostGIS.\n```\ncd openmaptiles\ndocker-compose run --rm -v $PWD:/omt import-data /bin/sh\nogr2ogr -f \"PostgreSQL\" PG:\"dbname=openmaptiles\" /omt/data/estaciones-de-bicicletas-zip/estaciones_de_bicicletas_WGS84.shp -nln ba_bike_sharing_stations -s_srs EPSG:4326 -t_srs EPSG:3857\nexit\n```\n\n### 6. Analyse bike sharing stations in PostGIS\n\n#### Add new table column\nEither in QGIS/Database/DB Manager... or in psql console\nAdd column `distance` with integer type.\n```\ncd openmaptiles\nmake psql\n\\d ba_bike_sharing_stations\nALTER TABLE ba_bike_sharing_stations ADD COLUMN distance INTEGER;\n\\d ba_bike_sharing_stations\n\\q\n```\n\n#### Distance analysis\nEither in QGIS/Database/DB Manager... or in psql console\n```\ncd openmaptiles\nmake psql\nUPDATE ba_bike_sharing_stations AS b SET distance=(SELECT ST_Distance(b.wkb_geometry, c.geometry) FROM osm_cycleway_linestring AS c ORDER BY b.wkb_geometry \u003c-\u003e c.geometry LIMIT 1);\n```\n\n### 7. Add analysed data into OpenMapTiles schema as a new layer cycleway_poi\n\n1. create new folder `cycleway_poi` in `layers` folder\n2. create new files `cycleway_poi.yaml` and `cycleway_poi.sql`\n3. add `layers/cycleway_poi/cycleway_poi.yaml` into list of layers in `openmaptiles.yaml`\n\n#### Layer definition file\n[cycleway_poi.yaml](./block-2/cycleway_poi/cycleway_poi.yaml)\n- `id` - id of layer used in style\n- `buffer_size` - buffer around layer for rendering purposes - should be bigger for layers with labels\n- `fields` - attributes definition\n- `datasource` - definition of the layer sql function\n- `schema` - additional sql files that should be run\n\n\n\n#### Layer sql function\n[cycleway_poi.sql](./block-2/cycleway_poi/cycleway_poi.sql)\n[cycleway_poi.sql](./block-2/cycleway_poi/cycleway_poi.sql)\n- `CREATE FUNCTION layer_cycleway_poi(bbox geometry, zoom_level int)`\n  - we want to create function with `bbox` and `zoom_level` as input params\n- `RETURNS TABLE (name text, geometry geometry, class text, hours text, distance integer)`\n  - function returns table with column `name`, `geometry`, `class` and `hours`. Column names match field names in `cycleway_poi.yaml`\n- `AS SELECT name, geometry, class, hours, distance FROM ba_bike_shops WHERE zoom_level \u003e= 12 UNION ALL ba_bike_sharing_stations WHERE zoom_level \u003e= 12`\n  - table consists of union of select from `ba_bike_shops` table and `ba_bike_sharing_stations` table.\n- `WHERE geometry \u0026\u0026 bbox;`\n  - WHERE condition assures that only data in given bbox will be returned\n\n### Rebuild\nWe modified schema, so we have to rebuild `build` folder before import.\n```\nmake clean\nmake\n```\n\n### Import sql\nRun import of sql files.\n```\nmake import-sql\n```\n\n## Block 3 - Generate, serve and style vector tiles\n\n\n\n[![Generate, serve and style vector tiles | FOSS4G 2021 Workshop Block #3](https://user-images.githubusercontent.com/59284/143771827-c40e4e06-3aaf-43d2-8cb3-47ece423f51d.jpeg)](https://www.youtube.com/watch?v=7aqGWjOxMWg\u0026list=PLGHe6Moaz52Mcq4BC9vczIIizNzwIYocv\u0026index=4\u0026ab_channel=MapTiler)\n\n\n\n### Generate vector tiles\nDuring the `make download` step, there should be `buenos-aires_city.bbox` file download \ninto `openmaptiles/data/south-america/argentina`.\nIt contains BBOX definition (area to be generated). If there is none, you can configure this in `.env` file.\n`BBOX=-58.535,-34.71,-58.331,-34.523`.\n\nThen you can generate tiles\n```\nmake generate-tiles-pg\n```\nGenerated tiles will be saved in `openmaptiles/data/tiles.mbtiles`\n\n\nThere are several ways to host your tiles e.g. MapTiler Cloud.\n\n### Upload tileset (tiles.mbtiles)\n\n0. If you used CloudShell and you do not have tiles.mbtiles generated on your computer you can download it from: https://dev.maptiler.download/foss4g/mbtiles/tiles.mbtiles\n1. Go to https://cloud.maptiler.com/\n2. Sign in with Google account.\n3. Go to `Tiles`, click on `NEW TILESET`\n4. Click on `SELECT A FILE FROM YOUR COMPUTER` and choose generated/downloaded tiles.mbtiles \n5. Detail page of `FOSS4G-Buenos Aires` tileset will show up. Use plus button in viewer to zoom in to Buenos Aires.\n6. Copy URL to TileJSON in `Vector tiles` section.\n\n### Add style to your tileset\n\n1. Download prepared style.json from https://dev.maptiler.download/foss4g/style/style.json\n2. Open style.json in editor and scroll down to section `sources`. Paste the URL to TileJSON.\n   ```\n   \"sources\": {\n       \"foss4g\": {\n           \"url\": \"https://api.maptiler.com/tiles/27a69314-5d8a-4ede-9878-f3e864f298a5/tiles.json?key=\u003cyour-API-key\u003e\",\n           \"type\": \"vector\"\n       },\n   ```\n   \u003e :warning: **Expired API key**: This API key was generated just for workshop purpose. Get your own at https://cloud.maptiler.com\n3. Save changes.   \n4. Go to `Maps` https://cloud.maptiler.com \n5. Click on `NEW MAP` and choose edited style.json.\n6. Detail page of `FOSS4G` map will show up.\n\n## Block 4 - Web \u0026 mobile app with custom map\n\n[![Web \u0026 mobile app with a custom map | FOSS4G 2021 Workshop Block #4](https://user-images.githubusercontent.com/59284/143771901-e68dbb01-c798-4134-8aaf-0194acb7481c.jpeg)](https://www.youtube.com/watch?v=sSq0axkwLU8\u0026list=PLGHe6Moaz52Mcq4BC9vczIIizNzwIYocv\u0026index=5\u0026ab_channel=MapTiler)\n\n\n### Web App\n\n[Sample Web App](https://labs.maptiler.com/foss4g-workshop/block-4/) which shows map prepared during the workshop and display information about bike shops and rentals.\n\u003e :warning: **Expired API key**: This Sample Web app uses expired API key, that was generated just for workshop purpose. Get your own at https://cloud.maptiler.com\n\n[The detailed tutorial](block-4/TUTORIAL.md)\n\n![web app screenshot](block-4/webapp.png \"Web App\")\n\n### Mobile App\n\nIt is also possible to use the custom app in mobile application:\n\n- Use MapTiler Mobile which is available on App Store/Google play Store. When you login using your account, you fill find the custom map in the list of available maps.  \n- You can build your own app following tutorials which are available on [mapTiler documentation site](https://www.maptiler.com/docs/)\n  - Android: [Custom Map tutorial](https://docs.maptiler.com/maplibre-gl-native-android/android-custom-map/)\n  - iOS: [Custom Map tutorial](https://docs.maptiler.com/maplibre-gl-native-ios/ios-swiftui-custom-map/)\n\n\u003cimg src=\"block-4/mobile.png\" width=\"400\" alt=\"mobile app screenshot\"\u003e\n\n\n[![MapLibre – Mapbox GL Native Open Source Fork | FOSS4G 2021 Buenos Aires, Petr Pokorny](https://user-images.githubusercontent.com/59284/143772097-d48eb927-9235-4aa4-85d8-d0c1397a4290.jpeg)](https://www.youtube.com/watch?v=pYbKJz6-q2w\u0026list=PLGHe6Moaz52Mcq4BC9vczIIizNzwIYocv\u0026index=8\u0026ab_channel=MapTiler)\n\nhttps://docs.maptiler.com/maplibre-gl-native-android/\n\nhttps://docs.maptiler.com/maplibre-gl-native-ios/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaptiler%2Ffoss4g-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaptiler%2Ffoss4g-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaptiler%2Ffoss4g-workshop/lists"}