{"id":51580040,"url":"https://github.com/blokzdev/websight_ai","last_synced_at":"2026-07-11T05:02:10.717Z","repository":{"id":363696944,"uuid":"1231604668","full_name":"blokzdev/websight_ai","owner":"blokzdev","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-10T00:46:57.000Z","size":762,"stargazers_count":0,"open_issues_count":7,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-10T02:15:17.534Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blokzdev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-07T05:46:10.000Z","updated_at":"2026-06-10T00:47:03.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/blokzdev/websight_ai","commit_stats":null,"previous_names":["blokzdev/websight_ai"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/blokzdev/websight_ai","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blokzdev%2Fwebsight_ai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blokzdev%2Fwebsight_ai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blokzdev%2Fwebsight_ai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blokzdev%2Fwebsight_ai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blokzdev","download_url":"https://codeload.github.com/blokzdev/websight_ai/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blokzdev%2Fwebsight_ai/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35351426,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-11T02:00:05.354Z","response_time":104,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2026-07-11T05:02:09.918Z","updated_at":"2026-07-11T05:02:10.707Z","avatar_url":"https://github.com/blokzdev.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WebSight\n\n[![CI](https://github.com/blokzdev/websight/actions/workflows/ci.yml/badge.svg)](https://github.com/blokzdev/websight/actions/workflows/ci.yml)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE)\n[![Flutter](https://img.shields.io/badge/Flutter-stable-02569B?logo=flutter)](https://flutter.dev)\n[![Use this template](https://img.shields.io/badge/Use%20this-template-2ea44f?logo=github)](https://github.com/blokzdev/websight/generate)\n\n**Declarative Android WebView app shell driven by a single\n`webview_config.yaml`.**\n\nTake any modern website and ship it to the Play Store with a hardened\nnative shell, JS bridge, AdMob + UMP consent, in-app updates, FCM,\nin-app purchases, and analytics — all without writing platform code.\n\nWebSight is **Android-only** (iOS is on the v1.x roadmap) and is\ndistributed as a GitHub template repository — click **Use this\ntemplate** to spin up your app, not a runtime.\n\n\u003e **Quick start:** click **[Use this template](https://github.com/blokzdev/websight/generate)**\n\u003e on GitHub, clone your new repo, run `dart run tool/init.dart`, and\n\u003e follow the prompts. ~5 minutes to a runnable debug APK.\n\n\u003c!--\n  TODO(screenshot): drop a 1200x675 PNG or short GIF of the running\n  demo (drawer + bottom tabs + AdMob banner) at docs/assets/hero.png\n  and uncomment the line below. Until then, the docs link to the\n  schema reference does the heavy lifting.\n\n  ![WebSight demo](./docs/assets/hero.png)\n--\u003e\n\n---\n\n## What you get\n\n- **Native-feel by default**: edge-to-edge with transparent system bars\n  (`flutter_ui.system_ui.mode: edge_to_edge`), so the wrapped site fills\n  the screen instead of looking like an embed. `viewport-fit=cover` and\n  `--websight-safe-*` CSS variables are auto-injected so the site can\n  inset its own header/footer with `env(safe-area-inset-*)`. A\n  defensive `\u003cbody\u003e` auto-pad (configurable via\n  `system_ui.auto_pad_body` + `auto_pad_edges`) catches sites that\n  don't natively read insets. Set `mode: default` for the standard\n  \"shell with chrome\" look.\n- **In-page features that actually work**: OAuth popups (`window.open` →\n  Flutter modal WebView, auto-closes when the provider redirects home),\n  HTML5 `\u003cvideo\u003e` fullscreen, in-page camera / mic /\n  `navigator.geolocation` prompts (one Android dialog, no separate\n  WebView popup). All toggleable in YAML.\n- **One YAML file**: theme, layout (drawer / bottom tabs / top tabs / none),\n  app bar actions, drawer / FAB, deep links, host allowlist, ads,\n  analytics, FCM, in-app updates, in-app purchases, splash, offline\n  fallback, custom CSS / JS injection — all in\n  `assets/webview_config.yaml`. Full schema reference at\n  [`docs/internal/config-reference.yaml`](./docs/internal/config-reference.yaml).\n- **Hardened WebView**: strict host allowlist, SSL block, file://\n  navigation block, scheme handoff (tel/mailto/intent/geo/market) to\n  Custom Tabs, configurable user agent (system / append / custom).\n- **JS bridge** (`window.WebSightBridge`): scanBarcode, share,\n  getDeviceInfo, downloadBlob, openExternal — all Promise-based with\n  stable error codes. Origin-gated by config. See\n  [`docs/bridge-api.md`](./docs/bridge-api.md).\n- **Native pieces**: ML Kit barcode scanner (CameraX), file uploads,\n  blob → MediaStore writes, FCM service with default channel, in-app\n  updates (flexible / immediate), Crashlytics + Analytics auto-screen\n  tracking.\n- **Compliance**: Google UMP consent gate before\n  `MobileAds.initialize()`; deny-by-default backups; HTTPS-only network\n  security config; Android 13+ runtime notification permission.\n- **Production gradle**: ProGuard/R8 rules, optional release signing,\n  multidex, `compileSdk = 36`, `minSdk = 24`.\n\n## Workflow: clone → ship\n\n**Fast path (recommended):**\n\n```bash\ngit clone \u003cthis-repo\u003e my-app \u0026\u0026 cd my-app\nflutter pub get\ndart run tool/init.dart        # interactive wizard — rich TUI or plain prompts\n```\n\nThe wizard walks identity / theme / disclaimer / features / splash;\nwrites `assets/webview_config.yaml`; runs the propagator; offers icons,\nnative splash, `flutterfire configure`, keystore generation, and a\nsmoke build. Re-runnable.\n\nThe condensed manual flow is below; the canonical end-to-end guide\n(toolchain, identity, icons, splash, Firebase, AdMob, signing, Play\nConsole, trademark/ToS guidance) lives in\n**[docs/WHITELABEL.md](./docs/WHITELABEL.md)**. Common questions\n(template vs fork, pulling upstream updates, multi-environment, what\nthe license allows, etc.) are in **[docs/FAQ.md](./docs/FAQ.md)**.\nDrop-in starter configs live in [examples/](./examples/). Run\n`dart run tool/doctor.dart` any time to survey project state.\n\n### 1. Start your project\n\nClick **[Use this template](https://github.com/blokzdev/websight/generate)**\non GitHub → \"Create a new repository\". This gives you a fresh repo\nwith no shared history, which you can keep private. Then clone your\nnew repo locally.\n\n(Plain `git clone` or **Fork** also work — fork only if you intend\nto send fixes back upstream. Each app you ship is an independent\nproject.)\n\n### 2. Install dependencies\n\n```bash\nflutter pub get\n```\n\n### 3. Edit identity in **one** place\n\n`assets/webview_config.yaml` is the single source of truth for app\nidentity. Set the `app:` block:\n\n```yaml\napp:\n  name: \"My Shop\"\n  host: \"shop.example.com\"\n  home_url: \"https://shop.example.com/\"\n  application_id: \"com.yourcompany.shop\"\n  admob_app_id: \"ca-app-pub-XXXXXXXXXX~YYYYYYYYYY\"\n  version: \"1.0.0+1\"\n```\n\nWhile you're here, set your routes, theme, allowlist, AdMob banner unit\nids (`ads.placements.*.ad_unit_id` — these are separate from the App ID\nin `app.admob_app_id` and are **not** touched by `tool/configure.dart`,\nsince they come from the AdMob console, not from app identity), FCM\nflags, splash, etc.\n\n### 4. Propagate identity to Android/Gradle/manifest/strings/pubspec\n\n```bash\ndart run tool/configure.dart           # apply\ndart run tool/configure.dart --dry-run # preview without writing\n```\n\nThe script keeps these files in sync with the YAML:\n\n- `android/app/build.gradle.kts` — `applicationId` + `namespace`\n- `android/app/src/main/AndroidManifest.xml` — deep-link\n  `\u003cdata android:host\u003e` + AdMob `APPLICATION_ID` meta-data\n- `android/app/src/main/res/values/strings.xml` — `app_name`\n- `pubspec.yaml` — `name` (snake_case) + `version`\n- `assets/webview_config.yaml` — `security.restrict_to_hosts` +\n  `navigation.deep_links.hosts` propagated from `app.host` so you only\n  edit one host\n\nIt is idempotent (re-run any time) and validates inputs (rejects empty\n`application_id`, malformed reverse-DNS, AdMob unit-ID-shaped values).\n\n### 5. (Optional) Move the Kotlin package directory to match\n\nThe script writes `applicationId` and `namespace`, but does **not** move\nKotlin source files. To rename the directory tree under\n`android/app/src/main/kotlin/com/...` to match your new\n`applicationId`, run:\n\n```bash\ndart run change_app_package_name:main com.yourcompany.shop\n```\n\nThis is destructive (moves files). **Order matters**: run this **before**\n`tool/configure.dart` (or re-run configure afterwards).\n`change_app_package_name` rewrites `build.gradle.kts` `applicationId` to\nits argument, so any value `tool/configure.dart` wrote previously will\nbe overwritten. The canonical sequence is therefore:\n\n```text\nedit YAML → change_app_package_name (optional) → tool/configure.dart\n```\n\nThe wizard at `dart run tool/init.dart` follows this order\nautomatically.\n\n### 6. Wire Firebase\n\n```bash\nnpm install -g firebase-tools         # if not already\ndart pub global activate flutterfire_cli\nflutterfire configure\n```\n\nThis regenerates `android/app/google-services.json` and\n`lib/firebase_options.dart` with your project's real values. The repo\nships placeholder versions so the project builds out of the box.\n\n### 7. Set up signing for release\n\nCreate `android/key.properties` (gitignored):\n\n```\nstorePassword=...\nkeyPassword=...\nkeyAlias=upload\nstoreFile=/absolute/path/to/upload-keystore.jks\n```\n\nIf `key.properties` is missing, release builds fall back to debug\nsigning — useful for quick smoke tests, but obviously not for the Play\nStore.\n\n### 8. (Optional) Customize the splash screen\n\nWebSight has two splash layers:\n\n- **Native pre-Flutter splash** — the first frame after process start,\n  before the Dart VM is up. Configured under `flutter_native_splash:`\n  in `pubspec.yaml`. Drop a logo at `assets/splash/logo.png`, point\n  `image:` at it, and run:\n\n  ```bash\n  dart run flutter_native_splash:create\n  ```\n\n- **In-Flutter splash overlay** — shown by `_SplashOverlay` while the\n  first WebView page loads. Configured under `splash:` in\n  `assets/webview_config.yaml`:\n\n  ```yaml\n  splash:\n    enabled: true\n    timeout_ms: 1500\n    fade_out_ms: 300\n    image_asset: \"assets/splash/logo.png\"\n    background_color: \"#0B0B0C\"\n    tagline: \"Loading…\"\n  ```\n\nBoth are optional. When neither is configured the app shows a brief\nsolid-color frame followed by the WebView's load progress.\n\n### 9. Build\n\n```bash\nflutter build appbundle --release\n```\n\nOutput: `build/app/outputs/bundle/release/app-release.aab`.\n\n## Project structure\n\n- `assets/webview_config.yaml` — **single source of truth** for both\n  runtime (theme, routes, ads, FCM, splash, downloads, JS bridge,\n  security) and build-time identity (app name, host, applicationId,\n  AdMob App ID).\n- `assets/websight.js` — bridge helper injected into every page.\n- `assets/offline/index.html` — offline fallback page.\n- `tool/configure.dart` — propagates the identity values from the\n  YAML into Gradle, manifest, strings, pubspec. Re-run any time the\n  YAML changes; it is idempotent.\n- `lib/config/` — typed config models (`webview_config.dart`,\n  `feature_configs.dart`).\n- `lib/shell/` — app shell, router, action dispatcher.\n- `lib/webview/` — WebView controller + screen.\n- `lib/bridge/` — Dart side of the JS bridge.\n- `lib/lifecycle/` — analytics, updates, permissions, FCM, billing,\n  rating.\n- `lib/native_screens/` — placeholder native screens you customize.\n- `android/app/src/main/kotlin/com/app/websight/` — `MainActivity` and\n  platform plugins (scanner, UMP consent, file uploads, FCM service).\n\n## Status\n\nWebSight is mid-flight on a v1 hardening pass. See\n[`docs/ROADMAP.md`](./docs/ROADMAP.md) for what is live, what is in\nprogress, and what is deferred.\n\n## Contributing\n\nSee [`CONTRIBUTING.md`](./CONTRIBUTING.md). PRs are welcome; the\nmaintained scope is the engine itself, not customer-specific\nintegrations.\n\n## License\n\n(Insert your chosen license here — MIT and Apache-2.0 are both common\nfor templates of this kind.)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblokzdev%2Fwebsight_ai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblokzdev%2Fwebsight_ai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblokzdev%2Fwebsight_ai/lists"}