{"slug": "proposta-workflow-md", "title": "PROPOSTA_WORKFLOW.md", "summary": "The article proposes a workflow to streamline the creation of Mapbox GL JS style JSONs for a frontend application. Currently, the process involves manual styling in Mapbox Studio, which is a bottleneck; the solution is to generate the style JSON directly in R using functions for continuous, categorical, and step-based data, and optionally automate tileset uploads via the Mapbox Uploads API. This eliminates the need for manual styling in Mapbox Studio, with the final deliverable being a style JSON, tileset ID, and source layer name for the developer.", "body_md": "Atualmente, o fluxo do Vinicius é:\n- Importar shapes e fazer limpeza no R\n- Exportar para geojson/mbtiles\n- Upload manual no Mapbox Studio\n- Estilização manual no Mapbox Studio (cores, breaks, etc.)\n- Copiar o JSON de estilo e colar no código\nO gargalo está na etapa 4 — a estilização manual no Mapbox Studio.\nO frontend espera um JSON de estilo no formato Mapbox GL JS expressions. Esse JSON pode ser gerado diretamente no R, sem precisar abrir o Mapbox Studio para estilizar.\nO Mapbox Studio passaria a ser usado apenas para upload do tileset (ou nem isso, se usar a API de uploads).\nR: limpeza dos dados\nR: definir cores, breaks, tipo de layer → gerar JSON de estilo\nR ou Mapbox Studio: upload do tileset\nEntregar ao dev: JSON de estilo + tileset ID + source layer name\nDev: colar no código (layer-styles.ts + city-layers.ts)\nO frontend precisa de um objeto JSON com esta estrutura:\n{\n\"id\": \"nome-do-layer\",\n\"type\": \"fill\",\n\"source\": \"composite\",\n\"source-layer\": \"nome_do_source_layer\",\n\"paint\": {\n\"fill-color\": [\n\"interpolate\",\n[\"linear\"],\n[\"get\", \"nome_da_propriedade\"],\n500, \"#fee5d9\",\n1000, \"#fcbba1\",\n1500, \"#fc9272\",\n2100, \"#fb6a4a\",\n2500, \"#ef3b2c\",\n3000, \"#cb181d\",\n3914, \"#99000d\"\n],\n\"fill-outline-color\": \"#000000\"\n},\n\"layout\": { \"visibility\": \"none\" },\n\"slot\": \"\"\n}\nAs variações possíveis de paint\nsão:\nPara dados numéricos contínuos (ex: densidade populacional):\nlibrary(jsonlite)\nlibrary(classInt)\n# Dados\nvalores <- seu_shapefile$Densidade_Populacional\n# Definir breaks (usando classInt ou manualmente)\nbreaks <- classIntervals(valores, n = 6, style = \"jenks\")$brks\n# Paleta de cores\ncores <- c(\"#e5f5f9\", \"#99d8c9\", \"#66c2a4\", \"#41ae76\", \"#238b45\", \"#00441b\")\n# Gerar a expressão interpolate do Mapbox GL\ngerar_interpolate <- function(propriedade, breaks, cores) {\nstops <- as.list(interleave(breaks, cores))\nlista <- list(\n\"interpolate\",\nlist(\"linear\"),\nlist(\"get\", propriedade)\n)\nlista <- c(lista, stops)\nreturn(lista)\n}\n# Função auxiliar para intercalar breaks e cores\ninterleave <- function(a, b) {\nn <- min(length(a), length(b))\nresultado <- vector(\"list\", 2 * n)\nresultado[seq(1, 2 * n, 2)] <- as.list(a[1:n])\nresultado[seq(2, 2 * n, 2)] <- as.list(b[1:n])\nreturn(resultado)\n}\n# Gerar o JSON completo do estilo\nestilo <- list(\nid = \"densidade-populacional-setor\",\ntype = \"fill\",\nsource = \"composite\",\n`source-layer` = \"densidade_populacional_setor\",\npaint = list(\n`fill-color` = gerar_interpolate(\"Densidade.Populacional\", breaks, cores),\n`fill-outline-color` = \"#000000\"\n),\nlayout = list(visibility = \"none\"),\nslot = \"\"\n)\n# Exportar para JSON\ncat(toJSON(estilo, auto_unbox = TRUE, pretty = TRUE))\n# Ou salvar em arquivo\nwrite(toJSON(estilo, auto_unbox = TRUE, pretty = TRUE), \"estilo_densidade.json\")\nPara dados categóricos (ex: tipo de tarifa):\ngerar_match <- function(propriedade, categorias, cores, cor_fallback = \"#000000\") {\nlista <- list(\n\"match\",\nlist(\"get\", propriedade)\n)\nfor (i in seq_along(categorias)) {\nlista <- c(lista, list(list(categorias[i])), list(cores[i]))\n}\nlista <- c(lista, list(cor_fallback))\nreturn(lista)\n}\ncategorias <- c(\"Integral\", \"Parcial\", \"Revogado\")\ncores <- c(\"#2166ac\", \"#80cdc1\", \"#b2182b\")\nestilo <- list(\nid = \"tarifa-zero\",\ntype = \"circle\",\nsource = \"composite\",\n`source-layer` = \"tarifa_zero_municipios\",\npaint = list(\n`circle-color` = gerar_match(\"Tipo de Tarifa Zero\", categorias, cores),\n`circle-radius` = 8\n)\n)\ncat(toJSON(estilo, auto_unbox = TRUE, pretty = TRUE))\nPara dados com faixas definidas:\ngerar_step <- function(propriedade, breaks, cores) {\n# step: cor_default, break1, cor1, break2, cor2, ...\nlista <- list(\n\"step\",\nlist(\"get\", propriedade),\ncores[1] # cor para valores abaixo do primeiro break\n)\nfor (i in 2:length(breaks)) {\nlista <- c(lista, list(breaks[i]), list(cores[i]))\n}\nreturn(lista)\n}\nPara eliminar também o upload manual no Mapbox Studio, é possível usar a API do Mapbox diretamente no R:\nlibrary(httr)\n# Upload de tileset via Mapbox Uploads API\nmapbox_token <- Sys.getenv(\"MAPBOX_SECRET_TOKEN\")\nusername <- \"observatorio-nacional\"\n# 1. Pedir credenciais de upload\ncreds <- GET(\npaste0(\"https://api.mapbox.com/uploads/v1/\", username, \"/credentials\"),\nquery = list(access_token = mapbox_token)\n)\ncreds_body <- content(creds)\n# 2. Upload do arquivo para S3 (usando as credenciais)\n# 3. Criar o tileset\n# Documentação: https://docs.mapbox.com/api/maps/uploads/\nOu usar o pacote mapboxapi\n:\n# install.packages(\"mapboxapi\")\nlibrary(mapboxapi)\nupload_tiles(\ninput = \"dados/meu_shapefile.geojson\",\nusername = \"observatorio-nacional\",\ntileset_id = \"meu_novo_tileset\",\ntileset_name = \"Meu Novo Tileset\",\nmultipart = TRUE\n)\nDepois de rodar o script R, o Vinicius entrega 3 coisas:\nAlém disso, os metadados para a UI:\nO Mapbox Studio se torna opcional — útil apenas para preview visual, não mais como ferramenta de produção.", "url": "https://wpnews.pro/news/proposta-workflow-md", "canonical_source": "https://gist.github.com/lucastavarex/7fc5a0859dbbe7c19f954eaffe9f1600", "published_at": "2026-03-18 00:13:03+00:00", "updated_at": "2026-05-22 21:05:58.953506+00:00", "lang": "en", "topics": ["developer-tools", "data"], "entities": ["Vinicius", "Mapbox Studio", "Mapbox GL JS", "R"], "alternates": {"html": "https://wpnews.pro/news/proposta-workflow-md", "markdown": "https://wpnews.pro/news/proposta-workflow-md.md", "text": "https://wpnews.pro/news/proposta-workflow-md.txt", "jsonld": "https://wpnews.pro/news/proposta-workflow-md.jsonld"}}