Cross-browser storage for all use cases, used across the web.

Overview

Store.js

Cross-browser storage for all use cases, used across the web.

Circle CI npm version npm

Store.js has been around since 2010 (first commit, v1 release). It is used in production on tens of thousands of websites, such as cnn.com, dailymotion.com, & many more.

Store.js provides basic key/value storage functionality (get/set/remove/each) as well as a rich set of plug-in storages and extra functionality.

  1. Basic Usage
  2. Supported Browsers
  3. Plugins
  4. Builds
  5. Storages

Basic Usage

All you need to know to get started:

API

store.js exposes a simple API for cross-browser local storage:

// Store current user
store.set('user', { name:'Marcus' })

// Get current user
store.get('user')

// Remove current user
store.remove('user')

// Clear all keys
store.clearAll()

// Loop over all stored values
store.each(function(value, key) {
	console.log(key, '==', value)
})

Installation

Using npm:

npm i store
// Example store.js usage with npm
var store = require('store')
store.set('user', { name:'Marcus' })
store.get('user').name == 'Marcus'

Using script tag (first download one of the builds):

<!-- Example store.js usage with script tag -->
<script src="path/to/my/store.legacy.min.js"></script>
<script>
store.set('user', { name:'Marcus' })
store.get('user').name == 'Marcus'
</script>

Supported Browsers

All of them, pretty much :)

To support all browsers (including IE 6, IE 7, Firefox 4, etc.), use require('store') (alias for require('store/dist/store.legacy')) or store.legacy.min.js.

To save some kilobytes but still support all modern browsers, use require('store/dist/store.modern') or store.modern.min.js instead.

List of supported browsers

Plugins

Plugins provide additional common functionality that some users might need:

List of all Plugins

Using Plugins

With npm:

// Example plugin usage:
var expirePlugin = require('store/plugins/expire')
store.addPlugin(expirePlugin)

If you're using script tags, you can either use store.everything.min.js (which has all plugins built-in), or clone this repo to add or modify a build and run make build.

Write your own plugin

A store.js plugin is a function that returns an object that gets added to the store. If any of the plugin functions overrides existing functions, the plugin function can still call the original function using the first argument (super_fn).

// Example plugin that stores a version history of every value
var versionHistoryPlugin = function() {
	var historyStore = this.namespace('history')
	return {
		set: function(super_fn, key, value) {
			var history = historyStore.get(key) || []
			history.push(value)
			historyStore.set(key, history)
			return super_fn()
		},
		getHistory: function(key) {
			return historyStore.get(key)
		}
	}
}
store.addPlugin(versionHistoryPlugin)
store.set('foo', 'bar 1')
store.set('foo', 'bar 2')
store.getHistory('foo') == ['bar 1', 'bar 2']

Let me know if you need more info on writing plugins. For the moment I recommend taking a look at the current plugins. Good example plugins are plugins/defaults, plugins/expire and plugins/events.

Builds

Choose which build is right for you!

List of default builds

Make your own Build

If you're using npm you can create your own build:

// Example custom build usage:
var engine = require('store/src/store-engine')
var storages = [
	require('store/storages/localStorage'),
	require('store/storages/cookieStorage')
]
var plugins = [
	require('store/plugins/defaults'),
	require('store/plugins/expire')
]
var store = engine.createStore(storages, plugins)
store.set('foo', 'bar', new Date().getTime() + 3000) // Using expire plugin to expire in 3 seconds

Storages

Store.js will pick the best available storage, and automatically falls back to the first available storage that works:

List of all Storages

Storages limits

Each storage has different limits, restrictions and overflow behavior on different browser. For example, Android has has a 4.57M localStorage limit in 4.0, a 2.49M limit in 4.1, and a 4.98M limit in 4.2... Yeah.

To simplify things we provide these recommendations to ensure cross browser behavior:

Storage Targets Recommendations More info
all All browsers Store < 1 million characters (Except Safari Private mode)
all All & Private mode Store < 32 thousand characters (Including Safari Private mode)
localStorage Modern browsers Max 2mb (~1M chars) limits, android
sessionStorage Modern browsers Max 5mb (~2M chars) limits
cookieStorage Safari Private mode Max 4kb (~2K chars) limits
userDataStorage IE5, IE6 & IE7 Max 64kb (~32K chars) limits
globalStorage Firefox 2-5 Max 5mb (~2M chars) limits
memoryStorage All browsers, fallback Does not persist across pages!

Write your own Storage

Chances are you won't ever need another storage. But if you do...

See storages/ for examples. Two good examples are memoryStorage and localStorage.

Basically, you just need an object that looks like this:

// Example custom storage
var storage = {
	name: 'myStorage',
	read: function(key) { ... },
	write: function(key, value) { ... },
	each: function(fn) { ... },
	remove: function(key) { ... },
	clearAll: function() { ... }
}
var store = require('store').createStore(storage)
Comments
  • feature: noop if no supported options found.

    feature: noop if no supported options found.

    Tried to use this package in a universal(read: isomorphic) app. It threw cannot read property 'documentElement' of undefined.

    What I was hoping that this package would just noop in the server and work as expected in the browser. I would be down to form a PR for this. It just involves checking for property existence.

    opened by BerkeleyTrue 15
  • 2.0.8 - No supported storage has been added

    2.0.8 - No supported storage has been added

    After upgrading from 2.0.4 to2.0.8, i got this error:

    Error: store.js: No supported storage has been added! Add one (e.g store.createStore(require('store/storages/cookieStorage')) or use a build with more built-in storages (e.g https://github.com/marcuswestin/store.js/tree/master/dist/store.legacy.min.js)

    opened by stunaz 13
  • Store is undefined when loading into a page that already uses AMD

    Store is undefined when loading into a page that already uses AMD

    We tried loading store.js into a site that had require.js (which was outside our control and loaded modules unrelated to what we were doing).

    We use window.store to access store. In this case, define.amd was defined so the code tries to call define(store) instead.

    Because window.store is not defined, our code doesn't run.

    NOTE: This is related to Issue #91 but is a different problem.

    opened by kgust 13
  • IE 7 throws error if number, or string starting with number, is used as key

    IE 7 throws error if number, or string starting with number, is used as key

    If you attempt to use a number, or a string starting with a number, as a key, then IE 7 will throw an error, e.g.

    This name may not begin with the '1' character
    

    I’m not sure if using numbers or strings starting with numbers as keys is meant to be supported, but it seems to work in IE 8 and other browsers.

    Test page:

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
    
        <script type="text/javascript" src="store.js"></script>
    
        <title>Test store.js</title>
    </head>
    <body>
    
    <button onclick="store.set('string', 'value');"><code>store.set('string', 'value')</code></button>
    
    <button onclick="store.set('123456', 'value');"><code>store.set('123456', 'value')</code></button>
    
    <button onclick="store.set(123456, 'value');"><code>store.set(123456, 'value')</code></button>
    
    <br>
    <br>
    
    <button onclick="alert(store.get('string', 'value'));"><code>store.get('string', 'value')</code></button>
    
    <button onclick="alert(store.get('123456', 'value'));"><code>store.get('123456', 'value')</code></button>
    
    <button onclick="alert(store.get(123456, 'value'));"><code>store.get(123456, 'value')</code></button>
    
    </body>
    
    </html>
    

    I’ve worked around the issue by patching store.js to append 'string_' to the key within the get(), set() and remove() functions passed to withIEStorage(), but I’m not sure if this is optimal.

    opened by pauldwaite 13
  • Compression plugin

    Compression plugin

    Closes #183

    • Adds a compression plugin, which uses get and set directly
    • Users can opt out of compression using an extra argument, ex) store.get('key', true), store.set('key', 'value', true)
    • Adds lz-string to plugins/lib
    • Simple compress and decompress tests

    This is pretty simple. I'm not sure how I should be handling namespacing, or if I even need to.

    opened by w33ble 11
  • SecurityError

    SecurityError

    I'm getting a Sentry report for Mobile Safari raising SecurityError when running Global.localStorage.

    store/storages/localStorage.js line 13:

    var localStorage = Global.localStorage
    

    User agent:

    Mozilla/5.0 (iPad; CPU OS 10_2_1 like Mac OS X) AppleWebKit/602.4.6 (KHTML, like Gecko) Version/10.0 Mobile/14D27 Safari/602.1
    
    opened by hyperknot 11
  • AMD implementation breaks sites

    AMD implementation breaks sites

    I finally found store.js while researching strange Javascript errors that I've encountered in my logs for some time now.

    It seems like some quite popular Chrome plugin uses store.js, so it gets executed on my site even though I do not use store.js myself.

    The problem is that store.js breaks my site! It confuses Dojo's AMD loader (and probably any other AMD loader too) when being loaded via a script tag in an AMD environment.

    So when a page or browser plugin includes it via <script src="store.min.js"></script> when e.g. the Dojo Toolkit was loaded before, store.js will call define(store), but the AMD loader will be unable to find out where that define came from and cannot determine any module ID. It will then fall back to the last used module ID, which can break things quite heavily.

    So define(store) should be changed to define('store', store) to provide an explicit module ID.

    opened by thomasbachem 11
  • Handle namespace

    Handle namespace

    Hi,

    It would be nice to be able to set a namespace when using store.js, because if you use store on your website and do a store.clear(), it clear all the localStorage and you can probably impact other websites that are using localStorage too.

    It could be something like :

    store.set('username', 'marcus') // 'username' => 'marcus'
    store.get('username') // 'marcus'
    store.clear() // clear ALL the localStorage
    
    store.namespace('myNameSpace'); 
    
    store.set('username', 'john') // 'myNameSpace.username' => 'john'
    store.get('username') // 'john'
    store.clear() // clear all myNameSpace keys in localStorage
    
    opened by Shuunen 10
  • isLocalStorage test improvement

    isLocalStorage test improvement

    in safari private mode, localStorage object is available but fails to store objects

    http://stackoverflow.com/questions/14555347/html5-localstorage-error-with-safari-quota-exceeded-err-dom-exception-22-an

    opened by stephane-tessier 10
  • Safari Private browsing mode appears to support localStorage, but doesn't

    Safari Private browsing mode appears to support localStorage, but doesn't

    Apparently this is by design. When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage is available, but trying to call .setItem throws an exception.

    store.js line 73 "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage that exceeded the quota."

    What happens is that the window object still exposes localStorage in the global namespace, but when you call setItem, this exception is thrown. Any calls to .removeItem are ignored.

    I believe the simplest fix (although I haven't tested this cross browser yet) would be to alter the function isLocalStorageNameSupported() to test that you can also set some value.

    currently:

    function isLocalStorageNameSupported() {
        try { return (localStorageName in win && win[localStorageName]) }
            catch(err) { return false }
    }
    

    proposed:

    function isLocalStorageNameSupported() {
        try { 
            var supported = (localStorageName in win && win[localStorageName]);
            if (supported) { localStorage.setItem("storage", ""); localStorage.removeItem("storage");
            return supported;
        }
        catch(err) { return false }
    }
    

    Of course it's kind of silly to call this every time you want to check that storage is supported, so you could memoize it, but you get the idea.

    opened by tjarratt 10
  • Feature request: Encrypted storage

    Feature request: Encrypted storage

    Goal

    Use encryption for storing data for non-public app areas.

    Description

    As far as I know, browsers store DOM storage on disk in unencrypted files, DOM storage is accessible from all domain paths (except IE UserData) and doesn't expire.

    This may be considered as security issue on shared workstations in cases when client-side app doesn't clear user data (browser crash/ closed window) or browser decides to keep them (temporary files).

    I see the simplest solution in encrypting storage data after serializing to JSON and decrypt before deserializing.

    It's up to the developer to come up with idea how to obtain secure key/ token; assuming encrypted storage makes sense for non-public areas (user is logged in), one can possibly use server-side unique session token. Once server-side session expires, token is not available anymore. When there is no token, previously saved data theoretically become undecryptable junk (and may be removed client-side on next execution).

    This should limit access to user data.

    Drawback: Storage values take quite more space (depends on encoding);

    Inspiration: dojo.storage.encrypted

    Implementation

    Configuration for Crypto.js, but any crypt library with methods encrypt( value ) and decrypt( encrypted ) should work:

    store.crypt = {
        key: App.token, // ie. 'c015dc1d6028a6815ac944c8512c10db',
        encrypt: function( plaintext ) {
            return CryptoJS.AES.encrypt( plaintext, this.key ).toString();
        },
        decrypt: function( encrypted ) {
            return CryptoJS.AES.decrypt( encrypted, this.key ).toString( CryptoJS.enc.Utf8 );
        }
    }
    

    Proposed changes to store.js code (didn't test):

    store.serialize = function(value) {
    
        var serialized = JSON.stringify( value );
    
        if ( store.crypt ) { serialized = store.crypt.encrypt( serialized ); }
    
        return serialized;
    }
    
    
    store.deserialize = function(value) {
    
        if ( typeof value !== 'string' ) { return undefined; }
    
        if ( store.crypt )
        {
            try {
                value = store.crypt.decrypt( value );
            } catch (e) {
                return undefined;
            }
        }
    
        return JSON.parse( value );
    }
    
    

    I'd like to discuss this idea with more proficient developers as I don't have much experience with client-side encryption.

    opened by piotr-cz 9
  • Bump shell-quote from 1.6.1 to 1.7.3

    Bump shell-quote from 1.6.1 to 1.7.3

    Bumps shell-quote from 1.6.1 to 1.7.3.

    Release notes

    Sourced from shell-quote's releases.

    v1.7.2

    • Fix a regression introduced in 1.6.3. This reverts the Windows path quoting fix. (144e1c2)

    v1.7.1

    • Fix $ being removed when not part of an environment variable name. (@​Adman in #32)

    v1.7.0

    • Add support for parsing >> and >& redirection operators. (@​forivall in #16)
    • Add support for parsing <( process substitution operator. (@​cuonglm in #15)

    v1.6.3

    • Fix Windows path quoting problems. (@​dy in #34)

    v1.6.2

    • Remove dependencies in favour of native methods. (@​zertosh in #21)
    Changelog

    Sourced from shell-quote's changelog.

    1.7.3

    • Fix a security issue where the regex for windows drive letters allowed some shell meta-characters to escape the quoting rules. (CVE-2021-42740)

    1.7.2

    • Fix a regression introduced in 1.6.3. This reverts the Windows path quoting fix. (144e1c2)

    1.7.1

    • Fix $ being removed when not part of an environment variable name. (@​Adman in #32)

    1.7.0

    • Add support for parsing >> and >& redirection operators. (@​forivall in #16)
    • Add support for parsing <( process substitution operator. (@​cuonglm in #15)

    1.6.3

    • Fix Windows path quoting problems. (@​dy in #34)

    1.6.2

    • Remove dependencies in favour of native methods. (@​zertosh in #21)
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump is-my-json-valid from 2.16.0 to 2.20.6

    Bump is-my-json-valid from 2.16.0 to 2.20.6

    Bumps is-my-json-valid from 2.16.0 to 2.20.6.

    Commits
    Maintainer changes

    This version was pushed to npm by linusu, a new releaser for is-my-json-valid since your current version.


    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump cached-path-relative from 1.0.1 to 1.1.0

    Bump cached-path-relative from 1.0.1 to 1.1.0

    Bumps cached-path-relative from 1.0.1 to 1.1.0.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • myJsonConverter function was applied to output of createStore function

    myJsonConverter function was applied to output of createStore function

    How to fix it

    To solve this problem, the explanations related to it were read first. After studying the code, searching, researching and developing (R&D) about this problem, it was finally solved as follows: First, Double quotation was converted to single quotation using regex format. Then the Parse function was used for this conversion.

    Erfan Kamalian web programming course -- Sharif University of Technology

    opened by ErfanKamalian 0
Owner
Marcus Westin
Technical founder, CTO and product architect. I love rapidly taking a product from 0 to launch, designing and coding much of it myself.
Marcus Westin
Cross domain local storage, with permissions

Cross domain local storage, with permissions. Enables multiple browser windows/tabs, across a variety of domains, to share a single localStorage. Feat

Zendesk 2.2k Jan 6, 2023
local storage wrapper for both react-native and browser. Support size controlling, auto expiring, remote data auto syncing and getting batch data in one query.

react-native-storage This is a local storage wrapper for both react native apps (using AsyncStorage) and web apps (using localStorage). ES6 syntax, pr

Sunny Luo 2.9k Dec 16, 2022
Browser storage interface for IndexedDB, WebSQL, LocalStorage, and in memory data with Schema and data validator.

Client Web Storage Browser storage interface for IndexedDB, WebSQL, LocalStorage, and in memory data with basic Schema and data validation. Installati

Before Semicolon 19 Sep 30, 2022
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.

localForage localForage is a fast and simple storage library for JavaScript. localForage improves the offline experience of your web app by using asyn

localForage 21.5k Jan 4, 2023
JS / CSS / files loader + key/value storage

bag.js - JS / CSS loader + KV storage bag.js is loader for .js / .css and other files, that uses IndexedDB/ WebSQL / localStorage for caching. Conside

Nodeca 86 Nov 28, 2022
A lightweight vanilla ES6 cookies and local storage JavaScript library

?? CrumbsJS ?? A lightweight, intuitive, vanilla ES6 fueled JS cookie and local storage library. Quick Start Adding a single cookie or a local storage

null 233 Dec 13, 2022
:sunglasses: Everything you need to know about Client-side Storage.

awesome-web-storage Everything you need to know about Client-side Storage. Table of Contents Introduction Browser Support Cookies Pros Cons API Useful

Varun Malhotra 420 Dec 12, 2022
An AngularJS module that gives you access to the browsers local storage with cookie fallback

angular-local-storage An Angular module that gives you access to the browsers local storage Table of contents: Get Started Video Tutorial Development

Gregory Pike 2.9k Dec 25, 2022
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.

localForage localForage is a fast and simple storage library for JavaScript. localForage improves the offline experience of your web app by using asyn

localForage 21.5k Jan 1, 2023
⁂ The simple file storage service for IPFS & Filecoin

⁂ web3.storage The simple file storage service for IPFS & Filecoin. Getting started This project uses node v16 and npm v7. It's a monorepo that use np

Web3 Storage 423 Dec 25, 2022
This is an upload script which allows you to upload to web3 storage using JS.

This is an upload script which allows you to upload to web3 storage using JS. first make sure to run npm install on the directory run script using nod

null 1 Dec 24, 2021
A javascript based module to access and perform operations on Linode object storage via code.

Linode Object Storage JS Module A javascript based module to access and perform operations on Linode object storage via code. Code Guardian Installing

Core.ai 3 Jan 11, 2022
Dustbin - Just Another Text Storage Service

Dustbin It's just another text storage service built in fastify. API Ofcouse we

Dustbin Server 25 Dec 3, 2022
Store your data in the world's fastest and most secure storage, powered by the blockchain technology⚡️

Store your data in the world's fastest and most secure storage, powered by the blockchain technology.

BlockDB 3 Mar 5, 2022
Expirable data storage based on localStorage and sessionStorage.

Expirable storage About The Project Expirable data storage based on localStorage and sessionStorage. Getting Started To get a local copy up and runnin

Wayfair Tech – Incubator 5 Oct 31, 2022
jStorage is a simple key/value database to store data on browser side

NB! This project is in a frozen state. No more API changes. Pull requests for bug fixes are welcomed, anything else gets most probably ignored. A bug

Andris Reinman 1.5k Dec 10, 2022
A simple, lightweight JavaScript API for handling browser cookies

JavaScript Cookie A simple, lightweight JavaScript API for handling cookies Works in all browsers Accepts any character Heavily tested No dependency S

null 20.2k Jan 3, 2023
AngularRoutingWebApp - Web App dimostrativa per spiegare e riepilogare i concetti basi di Angular.ts

RoutingApp This project was generated with Angular CLI version 11.0.2. Development server Run ng serve for a dev server. Navigate to http://localhost:

Gianmarco Polizzi 1 Jan 3, 2022
A mobile web application to check the data on the total covid19 confirmed cases and deaths, check data for all countries with recorded cases.

This is a mobile web application to check the data on the total covid19 confirmed cases and deaths, check data for all countries with recorded cases. It also has a details page to check for the statistics for each region/state if available.

Solomon Hagan 7 Jul 30, 2022
This is a Covid Cases Tracker Web app , with Malawi cases as priority .......coontact stevenkamwaza@gmail.. for more info

Getting Started with Create React App This project was bootstrapped with Create React App. for demo visit https://mwcovid-tracker.vercel.app/ Availabl

null 3 May 25, 2022