# π WebVirt: Load your SPA in Android WebView with just 3 lines of code
Tired of writing 100+ lines of boilerplate just to display a SPA in a WebView?
**WebVirt reduces it to 3 lines.**
---
## π© The problem (we've all been there)
Packaging a SPA (React, Vue, Angular, Svelte, SolidJs...) into an Android WebView should be trivial⦠but it's not:
- Manually configuring `WebViewClient`
- Intercepting requests (`shouldInterceptRequest`)
- Resolving SPA routes (`/products/42` β `index.html`)
- Handling MIME types correctly
- Implementing asset caching
- Preventing directory traversal attacks
- Controlling external traffic
All that⦠before you even start building your app.
---
## β¨ The solution: WebVirt
java
WebVirt.with(this)
.host("myapp.local")
.bind(webView);
webView.loadUrl("https://myapp.local/");
That's it.
WebVirt turns your APK into an internal virtual web server.
Your SPA lives in /assets and is served exactly like it would be in production.
---
π Offline-first security by default
WebVirt follows a simple rule:
If you don't explicitly allow it, it's blocked.
Β· π« External traffic blocked by default
Β· β
Whitelist with allowExternalDomains()
Β· π Offline mode with offlineOnly(true)
Β· π‘ Directory traversal protection
π¦ Automatic HTTP headers
java
WebVirt.with(this)
.host("myapp.local")
.allowExternalDomains("api.myapp.com", "cdn.myapp.com")
.bind(webView);
---
π§ Automatic SPA routing
Using React Router, Vue Router, or Angular?
WebVirt detects extensionless routes and serves index.html automatically:
Β· /about β index.html β
Β· /products/42 β index.html β
Β· /app.js β app.js β
Β· /style.css β style.css β
No configuration. No hacks. No 404s.
---
β‘ Smart in-memory caching
Optimized for real performance:
Β· π§ index.html β memory-cached (never stale)
Β· π¦ Assets (JS, CSS, JSON, WASM, fonts) β immutable cache (max-age=31536000)
java
webVirt.clearCache(); // Ideal in onDestroy()
---
π¦ Installation
settings.gradle
gradle
dependencyResolutionManagement {
repositories {
maven { url 'https://jitpack.io' }
}
}
build.gradle
gradle
dependencies {
implementation 'com.github.fouzstack:fouzstack-webvirt:v1.0.0'
}
---
π¨ Advanced configuration (optional)
java
WebVirt.with(this)
.host("myapp.local")
.subfolder("dist")
.allowExternalDomains("api.example.com")
.config(cfg -> {
cfg.setCacheEnabled(true);
cfg.setJavaScriptEnabled(true);
cfg.setDomStorageEnabled(true);
})
.bind(webView);
Full access to WebViewSettings without breaking the fluent API.
---
π Before vs After
Without WebVirt With WebVirt
~100 lines of code 3 lines
Manual WebViewClient Automatic
Broken SPA routing Works out-of-the-box
Manual caching Included
MIME type hell Included
Manual security Offline-first
---
π Repository
π github.com/fouzstack/fouzstack-webvirt
---
π€ Why "WebVirt"?
Because your APK becomes a:
Virtual web server without a real server
Β· No ports
Β· No network
Β· No real localhost
Just your SPA running like in production.
---
π§ͺ Requirements
Β· Android 4.4+ (API 19)
Β· AndroidX
Β· Compile SDK 34+
---
π License
MIT β use it without fear.
---
π Final thought
The best tools aren't the biggest.
They're the ones you set up in seconds⦠and then forget.
WebVirt doesn't want the spotlight.
It wants you to focus on your product.
---
β Did it help you?
Β· Star it on GitHub
Β· Open an issue if you find something
Β· PRs are welcome
Happy coding π
Top comments (0)