#GeoNode
Having fun with some Stickle bricks geonode setup!

#blender3d #geonodes #sticklebricks #nostalgia #procedural
November 4, 2026 at 10:26 AM
🚨 EUVD-2026-118479
📊 6.3/10
🏢 GeoNode

📝 GeoNode has Stored XSS in Documents metadata abstract field

🔗 https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-118479

#cybersecurity #infosec #cve #euvd
November 6, 2026 at 9:05 PM
Synthient found “a number of Windows 10 and Windows 11 devices on the White House’s network beaconing to known proxy providers like Geonode, Infatica and Mellowtel.”
2/6
November 6, 2026 at 7:33 PM
Synthient ha vinculat els dispositius infectats a SDK de l'app de festes Rave i a proveïdors coneguts com Geonode, Infatica (associada a ciberatacs de 2016) i Mellowtel.
November 6, 2026 at 6:05 PM
¡Nos vamos a las 𝗝𝗜𝗜𝗗𝗘 𝟮𝟬𝟮𝟲 en Oporto!

Luis Quesada presentará 𝗠𝘂𝗴𝗮𝗸𝗼 𝗕𝗶𝘀𝗼𝗿𝗲𝗮𝗸, un proyecto de la Fundación Peio Martikorena desarrollado con GeoNode y con Patricio Soriano como coautor.

📅 11/11 | 12:30 h (Portugal)

#JIIDE2026 #GIS #GeoNode

Nos vamos a Oporto en las Jornadas JIIDE 2026
Del 11 al 13 de noviembre estaremos en las JIIDE 2026.Nuestro director, Luis Quesada, presentará Mugako Bisoreak, una plataforma geográfica desarrollada por ...
f.mtr.cool
November 6, 2026 at 2:41 PM
django.core.exceptions.ImproperlyConfigured: Could not find the GDAL library . Try setting GDAL_LIBRARY_PATH in your settings. Windows 10-64 bit py39
When running paver setup attempting to configure Geonode (Windows 10-64bit, Python 39), I get a raise of django being improperly configured. The computer suggests that if I have installed GDAL successfully then I should try setting GDAL_LIBRARY_PATH in my settings. I have successfully installed gdal via pip install GDAL-3.3.1-cp39-cp39-win_amd64.whl. The settings for the geonode project are as follows (C:\Users\amell\Documents\geonode\geonode): if os.name == 'nt': import platform OSGEO4W = r"C:\OSGeo4W" if '64' in platform.architecture()[0]: OSGEO4W += "64" assert os.path.isdir(OSGEO4W), "Directory does not exist: " + OSGEO4W os.environ['OSGEO4W_ROOT'] = OSGEO4W os.environ['GDAL_DATA'] = OSGEO4W + r"\share\gdal" os.environ['PROJ_LIB'] = OSGEO4W + r"\share\proj" os.environ['PATH'] = OSGEO4W + r"\bin;" + os.environ['PATH'] I then added the below code to the above and still get the same issue: GDAL_LIBRARY_PATH = r'C:\OSGeo4W64\bin\gdal301.dll' I have in addition checked the lib names to see if the GDAL version I installed (331) is listed (C:\Users\amell\Documents\geonode_env\Lib\site-packages\django\contrib\gis\gdal\libgdal). Strangely, the .dll in C:\OSGeo4W64\bin is 301 and not 331 (others suggested renaming this which failed), though I installed 331 via pip using the .whl file. I am currently not sure what the problem is, I tried possible solutions suggested by those with the same issue and they do not seem to work for my case. Perhaps I am missing something.
gis.stackexchange.com
October 30, 2026 at 1:06 PM
Just the default one! I tried the Geonode one too, it performed a lot better but I couldn't figure how to make it sew.
October 29, 2026 at 5:58 AM
That just the stock blender-sim or are you playing with the new Geonode solver?
October 29, 2026 at 5:50 AM
🚀 Aprende a crear paneles de mando interactivos con #GeoNode para visualizar datos geoespaciales de manera efectiva. ¡Sigue a @SIGdeletras en el paso a paso! 🌍📊 

Creando un panel de mando en GeoNode: guía paso a paso
Aprende a crear un panel de mando en GeoNode . Visualiza datos geoespaciales y crea informes impactantes para la toma de decisiones.
f.mtr.cool
October 26, 2026 at 7:03 PM
sure! just found out that ErisGISScraper is on github! that's useful. i'll likely use a similar architecture, though i'm bit of a data hoarder so also considering a "download them all" approach

are you using TerriaMap/GeoNode for visualization, or entirely your own?
October 24, 2026 at 9:26 PM
October 23, 2026 at 1:52 PM
October 23, 2026 at 2:52 PM
How to use Random Flow's geonode feature. #b3d #blender3d #randomflow
How To Use Geonodes In Random Flow
YouTube video by Blender Guppy
www.youtube.com
October 16, 2026 at 1:24 PM
Print Composer for MapStore and GeoNode Crowdfunding https://www.geosolutionsgroup.com/print-composer-crowdfunding/
October 14, 2026 at 10:29 AM
Blog Archivi - GeoSolutions - GeoNode 5.1.0 Release by Giovanni Allegri

https://www.geosolutionsgroup.com/blog/geonode-5-1-0-release/
October 13, 2026 at 2:51 PM
How do I solve "django.db.utils.OperationalError: near "CASCADE": syntax error" in GeoNode install?
I have followed the Advanced Installation instructions for GeoNode Project, but at the Run GeoNode Project for the first time in DEBUG Mode step, it says to execute: # Prepare the GeoNode Spatialite database (the first time only) cd src/ chmod +x paver_dev.sh ./paver_dev.sh setup ./paver_dev.sh sync I should note that I am not running paver_dev.sh, but rather paver.sh. Here is the output when running ./paver.sh sync: ./paver.sh: line 1: /home/geonode/.override_env: No such file or directory ---> pavement.sync python -W ignore manage.py makemigrations --noinput Migrations for 'ratings': /home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/pinax/ratings/migrations/0004_auto_20230223_0126.py - Alter field category on overallrating - Alter field category on rating Migrations for 'upload': /home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/geonode/upload/migrations/0040_auto_20230223_0126.py - Alter field max_number on uploadparallelismlimit - Alter field max_size on uploadsizelimit python -W ignore manage.py migrate --noinput Operations to perform: Apply all migrations: account, actstream, admin, announcements, auth, avatar, base, br, contenttypes, django_celery_results, documents, favorite, geoapps, geonode_client, geonode_mapstore_client, geonode_resource_processing, geonode_themes, groups, guardian, harvesting, invitations, layers, management_commands_http, maps, monitoring, oauth2_provider, people, pinax_notifications, processing, ratings, resource, sequences, services, sessions, sites, socialaccount, taggit, tastypie, upload, user_messages Running migrations: Applying contenttypes.0001_initial... OK Applying taggit.0001_initial... OK Applying taggit.0002_auto_20150616_2121... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0001_initial... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying people.24_initial... OK Applying account.0001_initial... OK Applying account.0002_email_max_length... OK Applying actstream.0001_initial... OK Applying actstream.0002_remove_action_data... OK Applying actstream.0003_add_follow_flag... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying announcements.0001_initial... OK Applying announcements.0002_auto_20200311_0959... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying auth.0012_alter_user_first_name_max_length... OK Applying avatar.0001_initial... OK Applying avatar.0002_auto_20200210_1421... OK Applying base.24_initial... OK Applying layers.24_initial... OK Applying services.24_initial... OK Applying services.0025_harvestjob... OK Applying services.0026_auto_20171130_0600_squashed_0041_auto_20190404_0820... OK Applying layers.24_to_26... OK Applying layers.26_to_27... OK Applying base.24_to_26... OK Applying base.26_to_27... OK Applying base.0027_auto_20170801_1228_squashed_0037_auto_20190222_1347... OK Applying layers.0027_auto_20170801_1228_squashed_0033_auto_20180606_1543... OK Applying layers.0028_auto_20200610_0759... OK Applying layers.0029_auto_20200610_0803... OK Applying layers.0030_auto_20200610_0825... OK Applying layers.0031_auto_20200612_1533... OK Applying layers.0032_auto_20200612_1544... OK Applying services.0027_auto_20190429_0831... OK Applying services.0028_remove_service_last_updated... OK Applying services.0029_remove_service_created... OK Applying base.0028_curatedthumbnail... OK Applying base.0029_resourcebase_last_updated... OK Applying base.0030_resourcebase_created... OK Applying base.0031_auto_20200114_1651... OK Applying base.0032_auto_20200115_1121... OK Applying base.0033_auto_20200115_1145... OK Applying base.0034_auto_20200212_0410... OK Applying base.0035_auto_20200212_0428... OK Applying base.0036_resourcebase_doi... OK Applying base.0037_auto_20200305_1520... OK Applying base.0038_configuration... OK Applying base.0039_auto_20200321_1338... OK Applying base.0038_delete_backup... OK Applying base.0040_merge_20200321_2245... OK Applying groups.24_initial... OK Applying groups.26_to_27... OK Applying groups.0027_auto_20180105_1631_squashed_0028_auto_20180606_1543... OK Applying groups.0028_auto_20200114_1651... OK Applying groups.0029_auto_20200115_1121... OK Applying groups.0030_auto_20200221_1107... OK Applying groups.0031_auto_20200305_1522... OK Applying groups.0031_auto_20200304_1434... OK Applying groups.0032_merge_20200306_1153... OK Applying base.0038_auto_20200318_0953... OK Applying base.0041_merge_20200323_1119... OK Applying base.0042_auto_20200414_1554... OK Applying base.0043_auto_20200527_0833... OK Applying base.0044_resourcebase_bbox_polygon... OK Applying layers.0028_auto_20200323_1945... OK Applying layers.0033_merge_20200618_2150... OK Applying layers.0034_auto_20210329_1458... OK Applying layers.0035_auto_20210525_0847... OK Applying documents.24_initial... OK Applying documents.25_add_documentresourcelink_table... OK Applying documents.26_move_data_to_documentresourcelink_table... OK Applying documents.27_drop_resource_columns_from_document_table... OK Applying documents.0028_auto_20170801_1228_squashed_0035_auto_20190404_0820... OK Applying documents.0029_auto_20190429_0831... OK Applying documents.0030_auto_20200305_1520... OK Applying documents.0031_auto_20201107_2241... OK Applying base.0045_auto_20200507_0445... OK Applying base.0044_auto_20201001_1514... OK Applying base.0046_merge_20201016_0937... OK Applying base.0047_resourcebase_attribution... OK Applying base.0048_auto_20201116_0914... OK Applying base.0049_resourcebase_resource_type... OK Applying base.0050_auto_20210201_1008... OK Applying base.0051_auto_20210202_1656... OK Applying base.0052_auto_20210205_1631... OK Applying base.0053_auto_20210223_0905... OK Applying base.0054_auto_20210223_1202... OK Applying base.0055_auto_20210302_1109... OK Applying base.0056_resourcebase_ll_bbox_polygon... OK Applying base.0057_resourcebase_metadata_only... OK Applying base.0058_thesaurus_order... OK Applying base.0059_fill_empty_resource_type... OK Applying base.0060_auto_20210512_1658... OK Applying base.0061_auto_20211117_1238... OK Applying base.0062_resourcebase_extra_metadata... OK Applying base.0063_auto_20220128_1042... OK Applying base.0064_resourcebase_metadata... OK Applying base.0060_resourcebase_state... OK Applying base.0061_merge_0060_auto_20210512_1658_0060_resourcebase_state... OK Applying base.0062_resourcebase_files... OK Applying documents.0032_remove_document_doc_file... OK Applying base.0063_alter_resourcebase_files... OK Applying base.0064_alter_resourcebase_files... OK Applying base.0065_alter_curatedthumbnail_img... OK Applying base.0066_resourcebase_data... OK Applying base.0067_resourcebase_storetype... OK Applying base.0068_rename_storetype_resourcebase_subtype... OK Applying base.0069_resourcebase_sourcetype... OK Applying base.0070_auto_20210720_1709... OK Applying base.0071_remove_resourcebase_ows_url... OK Applying base.0072_remove_resourcebase_detail_url... OK Applying base.0073_resourcebase_thumbnail_path... OK Applying base.0074_drop_curated_thumbs... OK Applying base.0075_delete_curatedthumbnail... OK Applying base.0076_merge_20220204_1339... OK Applying base.0076_auto_20220128_0919... OK Applying base.0077_merge_20220204_1347... OK Applying base.0078_alter_resourcebase_metadata... OK Applying base.0079_alter_resourcebase_alternate... OK Applying base.0080_alter_resourcebase_uuid... OK Applying base.0081_alter_resourcebase_alternate... OK Applying base.0082_remove_dialogos_comment...Traceback (most recent call last): File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/backends/utils.py", line 82, in _execute return self.cursor.execute(sql) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 421, in execute return Database.Cursor.execute(self, query) sqlite3.OperationalError: near "CASCADE": syntax error The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/opt/geonode_custom/my_geonode/src/manage.py", line 31, in execute_from_command_line(sys.argv) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line utility.execute() File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/core/management/__init__.py", line 413, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/core/management/base.py", line 354, in run_from_argv self.execute(*args, **cmd_options) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/core/management/base.py", line 398, in execute output = self.handle(*args, **options) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/core/management/base.py", line 89, in wrapped res = handle_func(*args, **kwargs) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/core/management/commands/migrate.py", line 244, in handle post_migrate_state = executor.migrate( File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/migrations/executor.py", line 117, in migrate state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/migrations/executor.py", line 227, in apply_migration state = migration.apply(state, schema_editor) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/migrations/migration.py", line 126, in apply operation.database_forwards(self.app_label, schema_editor, old_state, project_state) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/migrations/operations/special.py", line 105, in database_forwards self._run_sql(schema_editor, self.sql) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/migrations/operations/special.py", line 130, in _run_sql schema_editor.execute(statement, params=None) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/backends/base/schema.py", line 145, in execute cursor.execute(sql, params) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/backends/utils.py", line 98, in execute return super().execute(sql, params) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/backends/utils.py", line 66, in execute return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers return executor(sql, params, many, context) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/backends/utils.py", line 79, in _execute with self.db.wrap_database_errors: File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/utils.py", line 90, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/backends/utils.py", line 82, in _execute return self.cursor.execute(sql) File "/home/geonode/.virtualenvs/my_geonode/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 421, in execute return Database.Cursor.execute(self, query) django.db.utils.OperationalError: near "CASCADE": syntax error Captured Task Output: --------------------- ---> pavement.sync python -W ignore manage.py makemigrations --noinput python -W ignore manage.py migrate --noinput Build failed running pavement.sync: Subprocess return code: 1 My vague understanding is that the CASCADE syntax is incompatible with the internal SQLite functionality, but I don't understand how to force it to use the PostGIS databases I set up earlier. How can I resolve this and get my GeoNode instance running in debug mode?
gis.stackexchange.com
October 7, 2026 at 9:07 PM
Hi Wafbuntu,

XXX here, I look after partnerships at Geonode. We pay apps to bundle our opt-in bandwidth sharing SDK. I came across Wafbuntu and it looks like a great fit: real users, and a tool that's free or close to it.

The way it works is simple. Your users get a clear consent prompt to sh[...]
See complete post at wafrn.jcm.re
wafrn.jcm.re is a Wafrn server. Wafrn is a federated social media inspired by Tumblr, join us and have fun!
wafrn.jcm.re
October 8, 2026 at 4:36 PM
Holy cow, nodebpy from @bradyajohnston.bsky.social gives Claude superpowers with blender. It can speak its native language. Geonode walls from a spline, gravestone generator, procedural ground, in just a few minutes. And unlike most ai-gen scenes, these are now tools that I can control and direct.
October 7, 2026 at 6:04 AM
¿Sabes qué es #GeoNode? 🌐 Descubre cómo esta plataforma de código abierto puede mejorar la gestión de tus datos geoespaciales en nuestro artículo.👇

https://f.mtr.cool/kh3cbmxnge

 #SIG #Geoinnova #Geoespacial #CódigoAbierto"
GeoNode, suite para la gestión colaborativa de datos geoespaciales
Conoce qué es Geonode y que características tiene esta alternativa de código abierto para construir una Infraestructura de Datos Espaciales.
f.mtr.cool
October 4, 2026 at 7:04 PM
Character suit using Random Flow's geonode and split by crease features. #b3d #blender3d #3dmodeling
October 3, 2026 at 3:01 PM
You want to kinda erode the edges, right? I'd geonode this with the new magical bevel node probably, maybe subdivide after too
October 1, 2026 at 8:23 PM
A React Native VPN Is Two Programs, and Only One of Them Is JavaScript
The first time someone asks "can we build our VPN in React Native?", the honest answer is yes, and the useful answer is that the VPN will not be written in React Native. JavaScript never touches a single packet. The tunnel lives in native code the operating system starts, keeps alive and kills on its own schedule. React Native gets to be the remote control. I learned this building a React Native VPN at Geonode, alongside the Repocket C# SDK. Every lesson worth keeping from that project was about one boundary: where your app ends and the part the OS owns begins. If you go in expecting to write it once in TypeScript, you lose weeks. If you go in expecting a thin cross-platform shell over two very different native engines, it is a perfectly reasonable way to ship. ## A VPN app is two programs pretending to be one This is the mental model that saved me the most time. 1. **The app** is what the user opens: a connect button, a server list, account state, maybe usage. React Native is genuinely good at this part. 2. **The tunnel** is what moves traffic. The OS starts it, keeps it alive and stops it, under rules you do not get to negotiate. On Android the tunnel is a `VpnService`. The first time, the user grants consent through a system dialog. The service creates a virtual network interface, the system routes traffic to it, it runs with a persistent notification, and it keeps running after the user swipes your app away. On iOS the tunnel is a packet tunnel provider inside a Network Extension. That is a separate target in the Xcode project, with its own bundle, its own entitlements and its own process. Your app does not run the tunnel. It asks the system to start a configuration, and the system launches the extension. The extension also runs under a much tighter memory budget than a normal app, which kills a lot of "just bundle a library" shortcuts. So the React Native part of the project is honestly the smallest part. The native modules and the extension are where the engineering lives. ## Keep the bridge embarrassingly small On the Repocket SDK my rule was "share the logic, never the platform." For a VPN, that turns into a deliberately tiny bridge between JavaScript and native. Roughly this, and nothing more: interface VpnBridge { connect(config: TunnelConfig): Promise<void>; disconnect(): Promise<void>; getStatus(): Promise<VpnStatus>; onStatusChange(cb: (s: VpnStatus) => void): () => void; checkPermission(): Promise<boolean>; requestPermission(): Promise<boolean>; } No packet handling, no routing decisions, no reconnection policy in JavaScript. Every time tunnel logic creeps into the JS side, you have written something that only runs while the app is open. The whole point of a VPN is that it keeps working when the app is not. ### One state vocabulary, mapped natively The thing you can share is vocabulary. Android and iOS report connection state differently, with different names, different intermediate states and different failure reasons. Each native module should map its platform's states into the same small set: type VpnStatus = | { state: "disconnected" } | { state: "connecting" } | { state: "connected" } | { state: "disconnecting" } | { state: "permission_required" } | { state: "error"; reason: string }; Doing that mapping in native code, per platform, means the UI renders one enum and you test one set of transitions. Many windows, one truth, and no window invents its own version of it. ## The OS owns the state. Your app only asks. This is the bug class that gets almost everyone the first time. The app keeps a variable that says "connected". The user closes the app. The tunnel keeps running. When the app comes back, it either thinks it is disconnected, or it thinks it is connected when the system tore the tunnel down an hour ago. The fix is easy to say: **the app never assumes, it asks.** On every launch and every return to the foreground, query the real status from the OS through the native module and render that. Anything cached in JavaScript is a hint for the first frame, never a fact. Three situations worth writing down as test cases before you write the UI: * **The app was killed but the tunnel is up.** Relaunch has to show connected, and disconnect still has to work. * **The system stopped the tunnel.** Another VPN app took over, the user turned it off in system settings, or the network changed. The UI has to reflect that without the user doing anything. * **Consent was revoked.** On both platforms the user can remove your VPN permission outside your app. The next connect must route through the permission step again instead of failing silently. In the SDK work I called this designing for being paused. Assume your process disappears at the worst possible moment, and make that a non-event. ## The tunnel has to be able to start without you Because the tunnel is a separate process on iOS, and effectively an independent service on Android, the app and the tunnel need a way to share configuration and report back. On iOS that usually means an App Group, a shared container both the app and the extension can read, plus the provider configuration you save through the system when you set the tunnel up. On Android the service lives in your app package, which makes sharing easier, but it still has to cope with being started by the system when your UI does not exist at all, for example when the user has turned on always-on VPN. The practical rule: **anything the tunnel needs to start, it must be able to read on its own.** If the tunnel only starts because JavaScript handed it a value in memory, it fails the first time the system starts it without you. And that first time will be on a user's phone, not yours. ## Store policy is part of the architecture VPN apps are a policy category on both stores, not just a technical one, and that shapes the plan more than people expect. On iOS, the packet tunnel needs the Network Extension capability on both the app and the extension, and Apple's review guidelines hold VPN apps to specific rules, including being offered by a developer enrolled as an organization rather than an individual account. If the plan is to ship under a personal developer account, find out in week one, not in the week you submit. On Android, apps using `VpnService` fall under Google Play policy on how the VPN is used and disclosed, and the persistent notification plus the consent dialog are part of the experience whether the design likes them or not. Design onboarding around the system consent step instead of trying to hide it. None of this is hard. It is just the kind of thing that turns a two-week estimate into a six-week one when nobody reads it up front. ## Real phones, and CI from day one I would not trust VPN behavior on a simulator or emulator for anything that matters. Network changes, sleep, switching from Wi-Fi to mobile data, the system killing the app, another VPN taking over: all of it has to be exercised on real phones, on both platforms, after every meaningful change to the native layer. The build is also more fragile than a normal React Native app. There is an extra iOS target, extra entitlements, provisioning profiles for both the app and the extension, and native modules that break on upgrades. If the only machine that can produce a working signed build is one engineer's laptop, you do not have a product, you have a dependency. Put both platforms on CI early, and make a broken extension build fail loudly the same day it breaks. ## So, React Native or native? React Native makes sense for a VPN when the team already writes TypeScript, the product has real UI beyond a connect button (accounts, server selection, usage, settings, onboarding), and you accept that you are owning two native tunnel implementations anyway. You get one app shell and one state vocabulary, and you pay for it with a bridge you must keep thin and honest. It makes less sense when the app really is one button. Then the UI you share is tiny, the native work dominates, and two small native apps can be the simpler path. Either way, the question is slightly wrong. The tunnel is native no matter what. The only decision is what draws the buttons. ## The short version * **Budget for native work first.** `VpnService` and the Network Extension are the project. * **Keep the bridge small.** Connect, disconnect, status, events, permission. * **Let the OS be the source of truth.** Ask on every launch and foreground. * **Make the tunnel self-sufficient.** It must start without your app running. * **Read the store rules in week one.** Account type, entitlements and disclosure change the plan. * **Real phones, CI builds.** Process death and network transitions do not show up on a laptop. The thing I keep relearning, from that SDK to AR work to the voice agents I build now, is the same: find the part the platform owns, respect it, and put the thinnest possible layer of your own code on top of it. _I originally wrote this for my site, with a few more links into the related SDK and CI posts: nabeelbaghoor.com._
dev.to
September 28, 2026 at 9:49 PM
I've fiddled with it a lot, including creating geonode setups to make it grow and shrink with the active camera distance (it makes Blender chug like crazy, had to create a switch to turn it off in the viewer)
September 17, 2026 at 12:49 PM
Most proxy vs scraping API comparisons are written by someone selling one of them. Geonode sells both, so pricing its two ladders against each other holds the vendor, the network and the date still.

https://www.proxy-compare.com/blog/proxy-or-scraping-api-the-break-even-math/
September 15, 2026 at 11:43 AM
🎉 New: GeoSolutions is a Bronze Sponsor of FOSS4G NA! 🎉

GeoSolutions is a global open-source #geospatial company with core developers and steering committee members of projects like GeoServer, MapStore, GeoNode, and GeoNetwork.

Learn more at:
www.foss4gna.org/202...

#GIS
September 10, 2026 at 1:50 PM