PWA-1P1A

1P1A (One Page One App) & OJapp Dynamic PWA Suite

Convert a page, directory, or entire site into a standalone Progressive Web App (PWA) with a lightweight client-side script and a dynamically generated Data URL Manifest.


🌟 Overview

1P1A (One Page One App) is a client-side PWA approach that removes the need to create and maintain a static manifest.json file for every page or tool.

Add an OJapp script to the page <head>, and it dynamically generates a Web App Manifest as a data:application/manifest+json URL. Depending on the selected mode, visitors can add an individual page, a directory group, or an entire site to their home screen with its own app name, description, icon, identity, start URL, navigation scope, and install presentation.

The core scripts require no build step, user registration, external API, or server-side manifest generation.


🚀 Key Features


đź’» Quick Start & App Structures

OJapp reads its meta tags when the script executes. Place all OJapp meta tags before the script tag.

1. 1P1A: One Page One App

Make the current page—or a query-configured instance of that page—an app on the user’s home screen.

<!-- Optional settings must come before the script -->
<meta name="ojapp:query" content="true">
<meta name="ojapp:title" content="My Custom Tool">
<meta name="ojapp:icon" content="/icon.png">

<script src="https://ojapp.app/js/ojapp_1p1a.js"></script>

Without optional meta tags, the page URL, page title, and available page icon are used automatically.

2. 1S1A: One Site One App

Make the entire origin a single unified app.

<script src="https://ojapp.app/js/ojapp_1s1a.js"></script>

By default, id, start_url, and scope use the origin root (/).

3. 1G1A: One Group One App

Turn a directory such as /dashboard/, /tools/, or /docs/ into its own app under the same origin.

<meta name="ojapp:id" content="/dashboard/">
<meta name="ojapp:start-url" content="/dashboard/">
<meta name="ojapp:scope" content="/dashboard/">

<script src="https://ojapp.app/js/ojapp_1s1a.js"></script>

Each directory group can use a different ID and scope, allowing multiple group apps under one origin without separate manifest files or build pipelines.


đź”— Query-Configured Apps

Enable query handling with:

<meta name="ojapp:query" content="true">

For example:

/timer/?time=5&mode=down&seconds=on&icon=blue

OJapp includes the current query string in the generated Manifest values for:

This allows the URL to store an app’s selected state while id distinguishes configured instances and start_url restores that state when the app launches.

Browsers process Manifest fields according to their own platform implementation. In particular, a browser may normalize or remove the query from the processed scope. OJapp still writes the configured query to all three fields and lets the browser perform that normalization.

If your page creates or changes the query after the initial load, navigate to or reload the final query URL before asking the user to add it to the home screen. A History API change alone may not update the URL captured by the iOS Add to Home Screen flow.


🖼️ Install Presentation

OJapp can customize the description and screenshots shown in supported browser install interfaces.

Install Description

Use ojapp:description when the install interface needs different copy from the page’s search description.

<meta
  name="ojapp:description"
  content="Install this tool for quick access from your home screen."
>

OJapp uses the following priority:

  1. ojapp:description
  2. Standard <meta name="description">
  3. No Manifest description when neither exists

This keeps search-oriented page copy separate from install-oriented messaging.

One Screenshot

Use the original unnumbered tag for a single image.

<meta
  name="ojapp:screenshot"
  content="/images/install.png"
>

Multiple Screenshots

Use numbered tags to add up to five images.

<meta name="ojapp:screenshot-1" content="/images/install-1.png">
<meta name="ojapp:screenshot-2" content="/images/install-2.png">
<meta name="ojapp:screenshot-3" content="/images/install-3.png">

If at least one numbered screenshot tag is present, the numbered set takes priority and the unnumbered ojapp:screenshot tag is ignored.

All screenshots in the set should use the same aspect ratio. A 1:1 square image is recommended because it remains easy to view in both desktop and mobile install interfaces. OJapp assigns the selected screenshots to wide on desktop and narrow on Android; the final layout is controlled by the browser.


🛠️ Metadata Reference

Meta Tag Applies To Description Default / Fallback
ojapp:title 1P1A / 1S1A Sets the app name 1P1A: page <title>; 1S1A: hostname
ojapp:description 1P1A / 1S1A Sets the Manifest install description Standard page meta description; otherwise omitted
ojapp:icon 1P1A / 1S1A Sets the app icon URL Available page icon, then OJapp default icon
ojapp:screenshot 1P1A / 1S1A Sets one install screenshot Omitted
ojapp:screenshot-1 through ojapp:screenshot-5 1P1A / 1S1A Sets up to five install screenshots; the numbered set takes priority Omitted
ojapp:query 1P1A / 1S1A Set to "true" to include the current query in id, start_url, and scope Disabled; query removed
ojapp:id 1S1A / 1G1A Sets the Manifest app identity Origin root
ojapp:start-url 1S1A / 1G1A Sets the URL opened from the home screen Origin root
ojapp:scope 1S1A / 1G1A Sets the navigation scope Origin root
ojapp:exclude 1P1A / 1S1A Set to "true" to disable OJapp on the page Disabled

All custom id, start_url, and scope values must resolve to the same origin as the current page.


📱 Platform Behavior

iOS / iPadOS (Safari)

Query-configured home screen entries have been verified on iPhone. Multiple entries created from the same page can retain different launch states, app names, and icons.

The installed icon can also depend on apple-touch-icon, so pages that dynamically select an icon should set it before the OJapp script executes.

Android (Chrome)

OJapp includes the query in the generated id, start_url, and scope. Chrome may normalize the processed navigation scope according to the Web App Manifest specification. Query-based multi-install identity can vary by browser and platform version, so test the intended behavior on the target Android device.


đź§­ Choosing a Mode

Mode App Unit Default Identity / Start / Scope Typical Use
1P1A Current page Current page path Tools, products, articles, profiles
1G1A Directory group Explicit directory path Dashboards, docs, grouped tools
1S1A Entire site Origin root / Conventional site-wide PWA

OJapp FREE

OJapp FREE provides a simple way to implement the 1P1A (One Page. One App.) and 1S1A (One Site. One App.) PWA design patterns.

For normal use, OJapp FREE is provided through the official hosted scripts at:

https://ojapp.app/

The production OJapp FREE runtime is not distributed as a JavaScript file from this repository.

Reference source code may be provided in this repository as .txt files for learning, research, modification, and independent implementation.

If you simply want to use OJapp FREE, please use the official hosted script described in the documentation.


License

Unless otherwise noted, source code contained in this repository is licensed under the MIT License.

See the LICENSE file for details.

The MIT License in this repository applies only to source code actually published in this repository.

The hosted OJapp FREE runtime provided from ojapp.app and OJapp PRO are separate from this repository and are not covered by this repository’s MIT License.

OJapp PRO is proprietary commercial software.


1P1A and UDA are Design Concepts

1P1A (One Page. One App.) and UDA (User Defined App) are PWA design concepts, not products.

1P1A describes a design approach where the application boundary is defined at the page level rather than the entire website.

UDA extends this idea further by allowing users to define an app through a specific URL state, such as query parameters.

OJapp is an implementation and service built around these concepts.

The MIT License in this repository applies only to the source code published here. It does not apply to the 1P1A or UDA concepts themselves.


🤝 Community & Feedback

Questions, test results, edge cases, and feature requests are welcome in this repository. Reference implementations may differ from the current production version of OJapp FREE and are not intended to track every update to the official hosted runtime.