├── public ├── favicon.ico ├── icons │ ├── icon-144.png │ ├── icon-152.png │ ├── icon-180.png │ ├── icon-192.png │ ├── icon-32.png │ └── icon-512.png ├── appcache-loader.html ├── manifest.json ├── index.html └── api │ └── countryCodes.json ├── images ├── s3-config-1.png ├── s3-config-2.png ├── s3-config-3.png ├── s3-waterfall.png └── visual-progress.png ├── scripts ├── README.md ├── build-preact.js ├── add-push-headers.js ├── generate-appcache.js ├── sw-precache-config.js └── aws-deploy.js ├── src ├── components │ ├── Title.js │ ├── Wrapper.js │ ├── Page.js │ ├── Nav.js │ ├── NavLink.js │ └── Seo.js ├── App.test.js ├── views │ ├── NoMatch.js │ ├── Countries.js │ ├── Home.js │ └── About.js ├── react.svg ├── index.css ├── index.js ├── App.js └── registerServiceWorker.js ├── .gitignore ├── firebase.base.json ├── README.md └── package.json /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/public/favicon.ico -------------------------------------------------------------------------------- /images/s3-config-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/images/s3-config-1.png -------------------------------------------------------------------------------- /images/s3-config-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/images/s3-config-2.png -------------------------------------------------------------------------------- /images/s3-config-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/images/s3-config-3.png -------------------------------------------------------------------------------- /images/s3-waterfall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/images/s3-waterfall.png -------------------------------------------------------------------------------- /public/icons/icon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/public/icons/icon-144.png -------------------------------------------------------------------------------- /public/icons/icon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/public/icons/icon-152.png -------------------------------------------------------------------------------- /public/icons/icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/public/icons/icon-180.png -------------------------------------------------------------------------------- /public/icons/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/public/icons/icon-192.png -------------------------------------------------------------------------------- /public/icons/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/public/icons/icon-32.png -------------------------------------------------------------------------------- /public/icons/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/public/icons/icon-512.png -------------------------------------------------------------------------------- /images/visual-progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stereobooster/an-almost-static-stack/react-snap/images/visual-progress.png -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | It feels like those scripts can be formed into the toolbox, like [kcd-scripts](https://github.com/kentcdodds/kcd-scripts) but I'm too lazy. 2 | -------------------------------------------------------------------------------- /src/components/Title.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export default styled.h1` 4 | font-size: 10vmin; 5 | line-height: 1em; 6 | font-weight: bold; 7 | ` 8 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import App from "./App"; 4 | 5 | it("renders without crashing", () => { 6 | const div = document.createElement("div"); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /src/components/Wrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export default styled.div` 4 | padding: 4rem 1rem; 5 | margin: 0 auto; 6 | @media (min-width: 801px) { 7 | width: 80vw; 8 | } 9 | max-width: 1140px; 10 | ` 11 | -------------------------------------------------------------------------------- /src/components/Page.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export default styled.div` 4 | h1 { 5 | font-size: 5vmin; 6 | font-weight: normal; 7 | color: #0000ff; 8 | } 9 | p { 10 | font-size: 0.9375rem; 11 | } 12 | ` 13 | -------------------------------------------------------------------------------- /scripts/build-preact.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = "production"; 2 | 3 | const config = require("react-scripts/config/webpack.config.prod"); 4 | 5 | config.resolve.alias["react"] = "preact-compat"; 6 | config.resolve.alias["react-dom"] = "preact-compat"; 7 | 8 | require("react-scripts/scripts/build"); 9 | -------------------------------------------------------------------------------- /src/views/NoMatch.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Seo from '../components/Seo' 3 | import Page from '../components/Page' 4 | 5 | export default () => ( 6 | 7 |

404?!

8 | 13 |
14 | ) 15 | -------------------------------------------------------------------------------- /public/appcache-loader.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | appCache loader 6 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | 6 | # testing 7 | coverage 8 | 9 | # production 10 | build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | npm-debug.log 16 | 17 | .firebaserc 18 | .firebase 19 | firebase-debug.log 20 | scripts/cache 21 | yarn-error.log 22 | firebase.json 23 | -------------------------------------------------------------------------------- /src/components/Nav.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export default styled.nav` 4 | padding: 1rem; 5 | background: #fff; 6 | border: 1px solid #e7e7e7; 7 | h1 { 8 | text-transform: uppercase; 9 | letter-spacing: 0.1em; 10 | font-size: 0.875rem; 11 | } 12 | > * { 13 | margin: 0 10px; 14 | display: inline-block; 15 | margin-top: 0; 16 | } 17 | ` 18 | -------------------------------------------------------------------------------- /src/react.svg: -------------------------------------------------------------------------------- 1 | 2 | React Logo 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, 5 | Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 6 | } 7 | 8 | *, 9 | *:before, 10 | *:after { 11 | box-sizing: border-box; 12 | } 13 | 14 | * { 15 | font-size: 1em; 16 | line-height: 1.4em; 17 | margin: 0; 18 | } 19 | 20 | * + * { 21 | margin-top: 1rem; 22 | } 23 | -------------------------------------------------------------------------------- /firebase.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "build", 4 | "headers": [ 5 | { 6 | "source": "service-worker.js", 7 | "headers": [ 8 | { 9 | "key": "Cache-Control", 10 | "value": "max-age=0" 11 | } 12 | ] 13 | }, 14 | { 15 | "source": "static/**/*.@(css|js|map)", 16 | "headers": [ 17 | { 18 | "key": "Cache-Control", 19 | "value": "max-age=31536000" 20 | } 21 | ] 22 | } 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { hydrate, render } from "react-dom"; 3 | import App from "./App"; 4 | import "./index.css"; 5 | // import registerServiceWorker from "./registerServiceWorker"; 6 | import { unregister } from "./registerServiceWorker"; 7 | import { BrowserRouter } from "react-router-dom"; 8 | 9 | const AppWithRouter = ( 10 | 11 | 12 | 13 | ); 14 | 15 | const rootElement = document.getElementById("root"); 16 | if (rootElement.hasChildNodes()) { 17 | hydrate(AppWithRouter, rootElement); 18 | } else { 19 | render(AppWithRouter, rootElement); 20 | } 21 | 22 | // registerServiceWorker(); 23 | unregister(); 24 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "yagd", 3 | "name": "yagd", 4 | "icons": [ 5 | { 6 | "src": "/icons/icon-144.png", 7 | "sizes": "144x144", 8 | "type": "image/png", 9 | "density": 3.0 10 | }, 11 | { 12 | "src": "/icons/icon-192.png", 13 | "sizes": "192x192", 14 | "type": "image/png", 15 | "density": 4.0 16 | }, 17 | { 18 | "src": "/icons/icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ], 23 | "start_url": "/index.html", 24 | "display": "standalone", 25 | "theme_color": "#F7E53B", 26 | "brand_color": "#F7E53B", 27 | "background_color": "#ffffff", 28 | "orientation": "portrait" 29 | } 30 | -------------------------------------------------------------------------------- /scripts/add-push-headers.js: -------------------------------------------------------------------------------- 1 | const FIREBASE_BASIC_CONFIG = "../firebase.base.json"; 2 | const FIREBASE_OUT_CONFIG = "../firebase.json"; 3 | const HTTP2_PUSH_MANIFEST = "../build/http2-push-manifest.json"; 4 | // const SERVICE_WORKER = "/service-worker.js"; 5 | 6 | const fs = require("fs"); 7 | const path = require("path"); 8 | 9 | const http2PushManifest = JSON.parse( 10 | fs.readFileSync(path.join(__dirname, HTTP2_PUSH_MANIFEST)) 11 | ); 12 | 13 | const firebaseBasicConfig = JSON.parse( 14 | fs.readFileSync(path.join(__dirname, FIREBASE_BASIC_CONFIG)) 15 | ); 16 | 17 | firebaseBasicConfig.hosting.headers = firebaseBasicConfig.hosting.headers.concat( 18 | http2PushManifest 19 | ); 20 | 21 | fs.writeFileSync( 22 | path.join(__dirname, FIREBASE_OUT_CONFIG), 23 | JSON.stringify(firebaseBasicConfig, null, 2) 24 | ); 25 | console.log(`Wrote ${FIREBASE_OUT_CONFIG}.`); 26 | -------------------------------------------------------------------------------- /src/components/NavLink.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Route, Link } from 'react-router-dom' 3 | import styled from 'styled-components' 4 | 5 | const NavLink = styled.div` 6 | a { 7 | transition: color 0.2s, border-bottom-color 0.2s; 8 | color: ${props => props.active ? '#0000ff' : '#666'}; 9 | text-decoration: none; 10 | border-bottom: 2px solid; 11 | border-bottom-color: ${props => props.active ? 'rgba(0, 0, 255, 0.1)' : 'transparent'}; 12 | &:hover, &:active, &:focus { 13 | color: ${props => props.active ? '#0000ff' : '#222'}; 14 | } 15 | } 16 | ` 17 | 18 | export default ({path, exact, reload, ...props}) => ( 19 | ( 20 | 21 | { reload ? 22 | {props.title} : 23 | {props.title} 24 | } 25 | 26 | )} /> 27 | ) 28 | -------------------------------------------------------------------------------- /scripts/generate-appcache.js: -------------------------------------------------------------------------------- 1 | const SW_PRECACHE_CONFIG = "./sw-precache-config"; 2 | const OUT_FILE = "../build/manifest.appcache"; 3 | 4 | const glob = require("globby"); 5 | const { 6 | staticFileGlobs, 7 | stripPrefix, 8 | navigateFallback 9 | } = require(SW_PRECACHE_CONFIG); 10 | const fs = require("fs"); 11 | const path = require("path"); 12 | 13 | glob(staticFileGlobs).then(files => { 14 | // filter out directories 15 | files = files.filter(file => fs.statSync(file).isFile()); 16 | // strip out prefix 17 | files = files.map(file => file.replace(stripPrefix, "")); 18 | 19 | const index = files.indexOf(navigateFallback); 20 | if (index > -1) { 21 | files.splice(index, 1); 22 | } 23 | 24 | const out = [ 25 | "CACHE MANIFEST", 26 | `# version ${new Date().getTime()}`, 27 | "", 28 | "CACHE:", 29 | ...files, 30 | "", 31 | "NETWORK:", 32 | "*", 33 | "http://*", 34 | "https://*", 35 | "", 36 | "FALLBACK:", 37 | `/ ${navigateFallback}` 38 | ].join("\n"); 39 | 40 | fs.writeFileSync(path.join(__dirname, OUT_FILE), out); 41 | console.log(`Wrote ${OUT_FILE} with ${files.length} resources.`); 42 | }); 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![An Almost Static Stack](https://i.imgur.com/NStGYap.jpg) 2 | 3 | # Disclaimer 4 | 5 | This is my "training" repository. I put here every trick that is possible. It doesn't mean you should do the same. Be reasonable use only those techniques that you understand. 6 | 7 | # An Almost Static Stack 8 | 9 | This repo serves as a companion to the [tutorial of the same name, over on Medium](https://medium.com/superhighfives/). 10 | 11 | ## Load performance optimization 12 | 13 | Read more [here](https://github.com/stereobooster/react-snap/blob/master/doc/an-almost-static-stack-optimization.md). 14 | 15 | ## TODO 16 | 17 | - [perfect 404](https://alistapart.com/article/perfect404) 18 | - try out [workbox](https://github.com/raymondsze/create-react-scripts/blob/master/packages/create-react-scripts-workbox/index.js) instead of sw-precache, explore [options for offline storages](https://github.com/jakearchibald/idb-keyval), explore offline reporting for GA 19 | - [big list of head tags](https://github.com/joshbuchea/HEAD) 20 | - [target modern browsers](https://philipwalton.com/articles/deploying-es2015-code-in-production-today/) 21 | - explore [hnpwa](https://hnpwa.com/) for more ideas 22 | -------------------------------------------------------------------------------- /scripts/sw-precache-config.js: -------------------------------------------------------------------------------- 1 | // Additional documentation 2 | // https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/config/webpack.config.prod.js#L325 3 | // https://github.com/GoogleChromeLabs/sw-precache#options-parameter 4 | module.exports = { 5 | // a directory should be the same as "reactSnap.destination", 6 | // which default value is `build` 7 | staticFileGlobs: [ 8 | "build/static/css/*.css", 9 | "build/static/js/*.js", 10 | "build/shell.html", 11 | "build/index.html" 12 | ], 13 | stripPrefix: "build", 14 | publicPath: ".", 15 | // there is "reactSnap.include": ["/shell.html"] in package.json 16 | navigateFallback: "/shell.html", 17 | // Ignores URLs starting from /__ (useful for Firebase): 18 | // https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219 19 | navigateFallbackWhitelist: [/^(?!\/__).*/], 20 | // By default, a cache-busting query parameter is appended to requests 21 | // used to populate the caches, to ensure the responses are fresh. 22 | // If a URL is already hashed by Webpack, then there is no concern 23 | // about it being stale, and the cache-busting can be skipped. 24 | dontCacheBustUrlsMatching: /\.\w{8}\./, 25 | // configuration specific to this experiment 26 | runtimeCaching: [ 27 | { 28 | urlPattern: /api/, 29 | handler: "fastest" 30 | } 31 | ] 32 | }; 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "devDependencies": { 6 | "highland": "^2.13.4", 7 | "level": "^4.0.0", 8 | "prettier": "^1.17.1", 9 | "react-scripts": "^3.0.1", 10 | "react-snap": "^1.23.0", 11 | "readdirp": "^2.2.1", 12 | "s3-sync-aws": "^1.1.1", 13 | "sw-precache": "^5.2.1", 14 | "uglifyjs": "^2.4.11" 15 | }, 16 | "dependencies": { 17 | "@loadable/component": "^5.10.1", 18 | "appcache-nanny": "^1.1.0", 19 | "preact": "^8.4.2", 20 | "preact-compat": "^3.18.4", 21 | "react": "^16.8.6", 22 | "react-dom": "^16.8.6", 23 | "react-helmet": "^5.2.1", 24 | "react-prerendered-component": "^1.2.2", 25 | "react-router-dom": "^5.0.0", 26 | "styled-components": "^2.2.3" 27 | }, 28 | "scripts": { 29 | "start": "react-scripts start", 30 | "build-react": "react-scripts build", 31 | "build-preact": "node scripts/build-preact.js", 32 | "build": "yarn run build-react && react-snap && yarn run generate-sw && yarn run generate-appcache", 33 | "test": "react-scripts test --env=jsdom", 34 | "eject": "react-scripts eject", 35 | "generate-fb": "node scripts/add-push-headers.js", 36 | "generate-sw": "sw-precache --root=build --config scripts/sw-precache-config.js && uglifyjs build/service-worker.js -o build/service-worker.js", 37 | "generate-appcache": "node scripts/generate-appcache.js", 38 | "aws-deploy": "node scripts/aws-deploy.js", 39 | "deploy": "yarn run build && yarn run generate-fb && firebase deploy", 40 | "prettier": "prettier --write {*,scripts/*,src/*}.{js,json,css}" 41 | }, 42 | "reactSnap": { 43 | "cacheAjaxRequests": true, 44 | "inlineCss": true, 45 | "http2PushManifest": true, 46 | "include": [ 47 | "/shell.html" 48 | ] 49 | }, 50 | "browserslist": [ 51 | ">0.2%", 52 | "not dead", 53 | "not ie <= 11", 54 | "not op_mini all" 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | React App 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /scripts/aws-deploy.js: -------------------------------------------------------------------------------- 1 | const _ = require("highland"); 2 | const level = require("level"); 3 | const s3sync = require("s3-sync-aws"); 4 | const readdirp = require("readdirp"); 5 | const fs = require("fs"); 6 | 7 | const db = level(__dirname + "/cache"); 8 | 9 | const files = readdirp({ 10 | root: __dirname + "/../build", 11 | directoryFilter: ["!.git", "!cache", "!.DS_Store"] 12 | }); 13 | 14 | const s3Options = { 15 | key: process.env.AWS_ACCESS_KEY, 16 | secret: process.env.AWS_SECRET_KEY, 17 | bucket: "yagd", 18 | concurrency: 16 19 | }; 20 | 21 | const longTermUploader = s3sync(db, { 22 | ...s3Options, 23 | headers: { 24 | CacheControl: "max-age=31536000" // 1 year 25 | } 26 | }).on("data", function(file) { 27 | console.log(`max-age=31536000 ${file.url}`); 28 | }); 29 | 30 | const uploader = s3sync(db, { 31 | ...s3Options, 32 | headers: { 33 | CacheControl: "max-age=14400" // 4 hours 34 | } 35 | }).on("data", function(file) { 36 | console.log(`max-age=14400 ${file.url}`); 37 | }); 38 | 39 | const shortTermUploader = s3sync(db, { 40 | ...s3Options, 41 | headers: { 42 | CacheControl: "max-age=180" // 3 minutes 43 | } 44 | }).on("data", function(file) { 45 | console.log(`max-age=180 ${file.url}`); 46 | }); 47 | 48 | const noCacheUploader = s3sync(db, { 49 | ...s3Options, 50 | headers: { 51 | CacheControl: "max-age=0" // no cache 52 | } 53 | }).on("data", function(file) { 54 | console.log(`max-age=0 ${file.url}`); 55 | }); 56 | 57 | _(files) 58 | .reject(x => x.path.match(/\.\w{8,10}\./gi)) 59 | .reject(x => x.path.indexOf("manifest.json") !== -1) 60 | .reject(x => x.path.indexOf(".DS_Store") !== -1) 61 | .reject(x => x.path.indexOf("asset-manifest.json") !== -1) 62 | .reject(x => x.path.indexOf(".html") !== -1) 63 | .reject(x => x.path.indexOf("service-worker.js") !== -1) 64 | .reject(x => x.path.indexOf("manifest.appcache") !== -1) 65 | .pipe(uploader); 66 | 67 | _(files) 68 | .filter( 69 | x => 70 | x.path.indexOf(".html") !== -1 || x.path.indexOf("manifest.json") !== -1 71 | ) 72 | .pipe(shortTermUploader); 73 | 74 | _(files) 75 | .filter( 76 | x => 77 | x.path.indexOf("service-worker.js") !== -1 || 78 | x.path.indexOf("manifest.appcache") !== -1 79 | ) 80 | .pipe(noCacheUploader); 81 | 82 | _(files) 83 | .filter(x => x.path.match(/\.\w{8,10}\./gi)) 84 | .pipe(longTermUploader); 85 | -------------------------------------------------------------------------------- /src/views/Countries.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Seo from '../components/Seo' 3 | import Page from '../components/Page' 4 | 5 | const CountriesRow = ({ country }) => ( 6 | 7 | {country.country_code} 8 | {country.country_name} 9 | {country.dialling_code} 10 | 11 | ) 12 | 13 | const CountriesTable = ({ countries }) => ( 14 | 15 | 16 | { countries.map(country => ) } 17 | 18 |
19 | ) 20 | 21 | const LoadableCountriesTable = ({state, countries}) => { 22 | switch (state) { 23 | case "loading": 24 | return
Loading
; 25 | case "loaded": 26 | return ; 27 | default: 28 | return
Error happened
; 29 | } 30 | } 31 | 32 | class Countries extends Component { 33 | constructor(props) { 34 | super(props); 35 | const url = props.url || "/api/countryCodes.json"; 36 | 37 | if (window.snapStore && window.snapStore[url]) { 38 | this.state = { 39 | url, 40 | state: "loaded", 41 | countries: window.snapStore[url]["countryCodes"] 42 | } 43 | } else { 44 | this.state = { 45 | url, 46 | countries: null, 47 | state: "loading" 48 | }; 49 | } 50 | } 51 | 52 | // componentWillReceiveProps(nextProps) { 53 | // if (nextProps.url !== this.state.url) { 54 | // this.setState({ 55 | // url: nextProps.url, 56 | // countries: null, 57 | // state: "loading" 58 | // }); 59 | // } 60 | // } 61 | 62 | componentDidMount() { 63 | console.log('componentDidMount', this.state.state) 64 | if (this.state.state !== "loading") return; 65 | 66 | fetch(this.state.url).then(async (response) => { 67 | const countries = (await response.json())["countryCodes"]; 68 | this.setState({ 69 | state: "loaded", 70 | countries 71 | }) 72 | }).catch(() => { 73 | this.setState({ 74 | state: "error" 75 | }) 76 | }) 77 | } 78 | 79 | render() { 80 | return ( 81 | 82 |

This is the Countries view.

83 | 84 | 89 |
90 | ) 91 | } 92 | } 93 | 94 | export default Countries 95 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { Route, Switch } from "react-router-dom"; 3 | import Helmet from "react-helmet"; 4 | import Wrapper from "./components/Wrapper"; 5 | import Title from "./components/Title"; 6 | import Nav from "./components/Nav"; 7 | import NavLink from "./components/NavLink"; 8 | 9 | import loadable from "@loadable/component"; 10 | import { PrerenderedComponent } from "react-prerendered-component"; 11 | 12 | const prerenderedLoadable = dynamicImport => { 13 | const LoadableComponent = loadable(dynamicImport); 14 | return React.memo(props => ( 15 | 16 | 17 | 18 | )); 19 | }; 20 | 21 | const Home = prerenderedLoadable(() => import("./views/Home")); 22 | const About = prerenderedLoadable(() => import("./views/About")); 23 | const Countries = prerenderedLoadable(() => import("./views/Countries")); 24 | const NoMatch = prerenderedLoadable(() => import("./views/NoMatch")); 25 | 26 | const title = "You Are Doing Great"; 27 | const routes = [ 28 | { 29 | title: "Home", 30 | path: "/", 31 | component: Home, 32 | exact: true 33 | }, 34 | { 35 | title: "About", 36 | path: "/about/", 37 | component: About 38 | }, 39 | { 40 | title: "Countries", 41 | path: "/countries/", 42 | component: Countries 43 | } 44 | ]; 45 | 46 | class App extends Component { 47 | constructor(props) { 48 | super(props); 49 | this.state = { 50 | serviceWorkerState: null 51 | }; 52 | this.onServiceWorkerNotification = this.onServiceWorkerNotification.bind( 53 | this 54 | ); 55 | } 56 | 57 | onServiceWorkerNotification(e) { 58 | this.setState({ 59 | serviceWorkerState: e.detail.state 60 | }); 61 | } 62 | 63 | componentWillMount() { 64 | let elem = window.document; 65 | elem.addEventListener( 66 | "serviceWorkerNotification", 67 | this.onServiceWorkerNotification, 68 | false 69 | ); 70 | } 71 | 72 | componentWillUnmount() { 73 | let elem = window.document; 74 | elem.removeEventListener( 75 | "serviceWorkerNotification", 76 | this.onServiceWorkerNotification, 77 | false 78 | ); 79 | } 80 | 81 | render() { 82 | return ( 83 | 84 | 85 | YADG 86 | 96 | 97 | {routes.map((route, i) => ( 98 | 99 | ))} 100 | null} 104 | /> 105 | 106 | 107 | 108 | ); 109 | } 110 | } 111 | 112 | export default App; 113 | -------------------------------------------------------------------------------- /src/components/Seo.js: -------------------------------------------------------------------------------- 1 | // code adapted from https://themeteorchef.com/tutorials/reusable-seo-with-react-helmet 2 | 3 | import React from 'react'; 4 | import PropTypes from 'prop-types'; 5 | import Helmet from 'react-helmet'; 6 | 7 | const absoluteUrl = path => `https://yagd-9d9f8.firebaseapp.com${path}`; 8 | const seoImageURL = file => `https://yagd-9d9f8.firebaseapp.com/images/${file}`; 9 | 10 | const getMetaTags = ({ 11 | title, description, url, contentType, published, updated, category, tags, twitter, image, 12 | }) => { 13 | const metaTags = [ 14 | { itemprop: 'name', content: title }, 15 | { itemprop: 'description', content: description }, 16 | { name: 'description', content: description }, 17 | { name: 'twitter:site', content: '@stereobooster' }, 18 | { name: 'twitter:title', content: `${title} | yagd-9d9f8.firebaseapp.com` }, 19 | { name: 'twitter:description', content: description }, 20 | { name: 'twitter:creator', content: twitter || '@stereobooster' }, 21 | { name: 'og:title', content: `${title} | yagd-9d9f8.firebaseapp.com` }, 22 | { name: 'og:type', content: contentType }, 23 | { name: 'og:url', content: url }, 24 | { name: 'og:description', content: description }, 25 | { name: 'og:site_name', content: 'yagd-9d9f8.firebaseapp.com' }, 26 | { name: 'og:locale', content: 'en_EN' }, 27 | // { name: 'fb:app_id', content: '' }, 28 | ]; 29 | 30 | if (published) metaTags.push({ name: 'article:published_time', content: published }); 31 | if (updated) metaTags.push({ name: 'article:modified_time', content: updated }); 32 | if (category) metaTags.push({ name: 'article:section', content: category }); 33 | if (tags) metaTags.push({ name: 'article:tag', content: tags }); 34 | if (image) { 35 | metaTags.push({ itemprop: 'image', content: seoImageURL(image) }); 36 | metaTags.push({ name: 'twitter:image:src', content: seoImageURL(image) }); 37 | metaTags.push({ name: 'og:image', content: seoImageURL(image) }); 38 | metaTags.push({ name: 'twitter:card', content: 'summary_large_image' }); 39 | } else { 40 | metaTags.push({ name: 'twitter:card', content: 'summary' }); 41 | } 42 | 43 | return metaTags; 44 | }; 45 | 46 | const getHtmlAttributes = ({ 47 | schema 48 | }) => { 49 | let result = { 50 | lang: 'en', 51 | }; 52 | if (schema) { 53 | result = { 54 | ...result, 55 | itemscope: undefined, 56 | itemtype: `http://schema.org/${schema}`, 57 | } 58 | } 59 | return result; 60 | } 61 | 62 | getHtmlAttributes.propTypes = { 63 | schema: PropTypes.string, 64 | }; 65 | 66 | const Seo = ({ 67 | schema, title, description, path, contentType, published, updated, category, tags, twitter, 68 | }) => ( 69 | 89 | ); 90 | 91 | Seo.propTypes = { 92 | schema: PropTypes.string, 93 | title: PropTypes.string, 94 | description: PropTypes.string, 95 | path: PropTypes.string, 96 | contentType: PropTypes.string, 97 | published: PropTypes.string, 98 | updated: PropTypes.string, 99 | category: PropTypes.string, 100 | tags: PropTypes.array, 101 | twitter: PropTypes.string, 102 | image: PropTypes.string, 103 | }; 104 | 105 | export default Seo; 106 | -------------------------------------------------------------------------------- /src/views/Home.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Page from '../components/Page' 3 | import Seo from '../components/Seo' 4 | 5 | export default () => ( 6 | 7 |

This is the Home view.

8 |

Scelerisque venenatis nibh fames ad quam feugiat leo commodo vitae sed lacus duis habitant maecenas sem interdum quisque duis mauris scelerisque scelerisque dui elit a condimentum vestibulum ad vestibulum. Laoreet nostra dui vivamus vestibulum integer taciti suscipit consectetur in a nullam quam nam ad nunc class nec ullamcorper urna sed nascetur ad. Vestibulum a sem leo nunc condimentum vestibulum euismod sapien aenean adipiscing a mi volutpat non fames. Adipiscing parturient parturient sit nec viverra tristique dui senectus commodo sem eu vestibulum vestibulum lorem ullamcorper. A quis a volutpat posuere suspendisse commodo nec elit parturient parturient sit ac sed suspendisse nam ullamcorper. Sit in a ut vivamus fringilla penatibus suspendisse scelerisque eu bibendum a egestas sodales vel rhoncus phasellus suspendisse faucibus viverra ultricies fusce laoreet libero a taciti.

9 |

Elementum cras id suspendisse mi ut eros elit a enim curabitur posuere adipiscing eleifend auctor dictumst hac porttitor iaculis dis. Ut porttitor neque etiam primis et vestibulum parturient consectetur a etiam class consectetur a in massa parturient hac sed litora massa. Arcu enim arcu ac interdum ullamcorper consectetur aptent natoque curae mattis adipiscing a non metus netus arcu accumsan nam quisque condimentum posuere platea congue nisl mollis id nascetur.

10 |

Facilisis diam adipiscing ut eu porta cubilia donec scelerisque suspendisse suspendisse parturient a elit adipiscing in eu porttitor at suspendisse suspendisse placerat. Faucibus vestibulum habitasse ac dignissim a interdum fringilla nisi tortor eget dictum netus curae a pulvinar semper feugiat pharetra. Cras facilisis feugiat mi urna nec porttitor id leo suspendisse suspendisse phasellus parturient lacus lobortis condimentum a mus. Mi nam phasellus ridiculus est nisl nullam maecenas eu a erat proin facilisis at massa sit ac aenean tempus sed pharetra curabitur gravida nulla dapibus in. Dolor venenatis sit ullamcorper suspendisse eu ac ridiculus a adipiscing et a suscipit lectus turpis volutpat lectus tincidunt per rutrum vestibulum consectetur consectetur adipiscing quam.

11 |

Ullamcorper enim morbi adipiscing ac lacinia vestibulum tempor a pulvinar mauris natoque litora lectus a senectus. Parturient a sagittis viverra consectetur convallis in auctor dapibus vestibulum facilisi parturient ullamcorper vulputate a ullamcorper pulvinar justo platea fermentum aptent. Lectus condimentum vestibulum ut faucibus vulputate a feugiat aliquet faucibus platea iaculis sed condimentum vulputate scelerisque a eu in mi ullamcorper scelerisque adipiscing et fames parturient mollis adipiscing varius.

12 |

Donec et pulvinar mi elementum parturient penatibus id dui scelerisque adipiscing egestas urna pharetra praesent scelerisque. Ullamcorper quis hendrerit a elit mi sit dis vestibulum fringilla mi pulvinar in erat aptent vestibulum nisi a enim vestibulum parturient. Laoreet ad in aliquet magna accumsan donec fringilla tellus consectetur vulputate dui interdum nisl sociis aliquam sociis adipiscing quisque adipiscing et velit.

13 |

Sit vitae id ullamcorper adipiscing adipiscing nunc a vitae litora dolor consectetur primis parturient ligula. Sit porttitor luctus hac eu purus parturient phasellus ullamcorper eros hac malesuada aliquet suspendisse duis laoreet cum augue proin consectetur feugiat a scelerisque taciti ullamcorper parturient. Ut vel parturient parturient consectetur vel eros quisque tellus etiam parturient integer eleifend quisque condimentum faucibus congue nisi facilisi quam a pharetra viverra montes. Ad magna a curae turpis auctor condimentum nulla massa ligula himenaeos tempor a integer condimentum integer.

14 | 19 |
20 | ) 21 | -------------------------------------------------------------------------------- /src/views/About.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Seo from '../components/Seo' 3 | import Page from '../components/Page' 4 | import svg from '../react.svg' 5 | 6 | export default () => ( 7 | 8 |

This is the About view.

9 | 10 |

Ante himenaeos a vestibulum dignissim cursus porta a amet blandit massa netus parturient ac diam faucibus a vestibulum scelerisque dapibus ante vivamus praesent diam. Est duis dapibus parturient a a tristique duis adipiscing nam vivamus natoque habitasse suspendisse eu curabitur pretium scelerisque sodales consectetur est a augue conubia natoque penatibus ligula lacus. Parturient sagittis vulputate parturient urna ipsum aliquam suspendisse diam adipiscing at a massa urna maecenas litora inceptos pulvinar tempus odio pharetra mi platea nunc viverra. Parturient venenatis ipsum suspendisse ullamcorper nam himenaeos natoque sem auctor non et odio ridiculus elit volutpat vestibulum nisl a vestibulum libero cum molestie vestibulum. Condimentum sem magnis erat curae duis ut gravida parturient accumsan egestas a vestibulum suscipit a a at turpis varius sociis.

11 |

Quisque aliquet rhoncus est quisque torquent velit orci luctus consectetur pharetra consectetur ac proin cras a consequat scelerisque dictumst faucibus. Id condimentum consectetur gravida donec cursus duis a vehicula parturient volutpat euismod habitant litora vestibulum a ad vestibulum sed. Dui amet nam vestibulum ipsum consectetur dapibus eu tempus vel a nec proin ornare nibh. Nunc cras tristique a eu non nunc auctor phasellus nisi porttitor tempus ad sodales at. A parturient adipiscing non neque morbi felis libero taciti fusce quisque tortor a posuere augue diam placerat vestibulum varius montes suspendisse parturient id. Iaculis suspendisse consectetur vitae libero a lectus quisque enim vulputate adipiscing fames viverra gravida vestibulum ullamcorper.

12 |

Accumsan dui nullam id suspendisse vestibulum fames lobortis id sit vehicula pretium mus accumsan non volutpat mi. Ad orci ligula dis venenatis a maecenas tempor per nullam egestas vestibulum penatibus a suspendisse vel nulla tempus per scelerisque elit sed quisque sapien vestibulum ac cum enim a. Eleifend quam vestibulum diam suspendisse eu inceptos est iaculis in eros vestibulum velit class a massa diam potenti. Parturient ligula a diam integer nullam vestibulum platea ad donec a a inceptos ac cubilia condimentum habitant in ridiculus quisque sit. Duis sit mi augue leo adipiscing condimentum nostra a eu adipiscing sapien massa felis vestibulum senectus et taciti sodales.

13 |

Iaculis ac vestibulum ullamcorper parturient et dis a parturient congue enim ante nostra adipiscing lobortis a. Ullamcorper condimentum aliquet in commodo ligula velit himenaeos ad metus interdum eu fringilla mi vulputate eu platea sed integer. Gravida pulvinar per nisi fames nascetur ut metus ipsum leo scelerisque habitasse iaculis enim ad luctus molestie vestibulum a montes suspendisse nisi eget primis eleifend quisque dui parturient.

14 |

Cum class adipiscing aenean primis sed a ultricies himenaeos senectus bibendum interdum vel eleifend at justo. At ultricies posuere ullamcorper turpis praesent quam curae convallis suspendisse nullam parturient consequat sem condimentum rutrum eget. Luctus turpis facilisi potenti condimentum consectetur euismod ut in eu ac fringilla pulvinar a magna. Nisi gravida eu quisque egestas adipiscing adipiscing magna nam integer suspendisse et cubilia parturient nisl ut in suscipit a sit dapibus vestibulum nec condimentum a a. Eros libero ac quis vestibulum potenti lorem a a consectetur facilisis porta ultrices at sodales. Vestibulum adipiscing iaculis velit lacus mollis consectetur scelerisque mattis sapien parturient porta bibendum ultricies id urna ligula gravida curae facilisis.

15 |

A sem vel nec sodales mi vivamus senectus sed potenti a parturient nascetur tincidunt nisi pulvinar rhoncus a. Risus imperdiet taciti suspendisse facilisi a per metus cubilia varius a nostra adipiscing amet ultrices quisque ac mi a. Dictumst a ultrices mi a dignissim ad fermentum eget a nam et a blandit scelerisque. Taciti lorem tempor quam vestibulum dis habitasse vestibulum diam vel est ut proin dis auctor. Suscipit scelerisque orci magna interdum vel bibendum duis netus a consectetur dui magnis ac aliquet sem posuere tincidunt vestibulum.

16 | 21 |
22 | ) 23 | -------------------------------------------------------------------------------- /src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | // In production, we register a service worker to serve assets from local cache. 2 | 3 | // This lets the app load faster on subsequent visits in production, and gives 4 | // it offline capabilities. However, it also means that developers (and users) 5 | // will only see deployed updates on the "N+1" visit to a page, since previously 6 | // cached resources are updated in the background. 7 | 8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. 9 | // This link also includes instructions on opting out of this behavior. 10 | 11 | import appCacheNanny from "appcache-nanny"; 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === "localhost" || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === "[::1]" || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export default function register() { 24 | if (process.env.NODE_ENV !== "production") return; 25 | 26 | if ("serviceWorker" in navigator) { 27 | // The URL constructor is available in all browsers that support SW. 28 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location); 29 | if (publicUrl.origin !== window.location.origin) { 30 | // Our service worker won't work if PUBLIC_URL is on a different origin 31 | // from what our page is served on. This might happen if a CDN is used to 32 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 33 | return; 34 | } 35 | 36 | window.addEventListener("load", () => { 37 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 38 | 39 | if (isLocalhost) { 40 | // This is running on localhost. Lets check if a service worker still exists or not. 41 | checkValidServiceWorker(swUrl); 42 | 43 | // Add some additional logging to localhost, pointing developers to the 44 | // service worker/PWA documentation. 45 | navigator.serviceWorker.ready.then(() => { 46 | console.log( 47 | "This web app is being served cache-first by a service " + 48 | "worker. To learn more, visit https://goo.gl/SC7cgQ" 49 | ); 50 | }); 51 | } else { 52 | // Is not local host. Just register service worker 53 | registerValidSW(swUrl); 54 | } 55 | }); 56 | } else if (window.applicationCache) { 57 | appCacheNanny.start(); 58 | appCacheNanny.on("updateready", () => { 59 | let event = new CustomEvent("serviceWorkerNotification", { 60 | detail: { 61 | state: "new" 62 | } 63 | }); 64 | window.document.dispatchEvent(event); 65 | console.log("New content is available; please refresh."); 66 | }); 67 | appCacheNanny.on("cached", () => { 68 | let event = new CustomEvent("serviceWorkerNotification", { 69 | detail: { 70 | state: "cached" 71 | } 72 | }); 73 | window.document.dispatchEvent(event); 74 | console.log("Content is cached for offline use."); 75 | }); 76 | } 77 | } 78 | 79 | function registerValidSW(swUrl) { 80 | navigator.serviceWorker 81 | .register(swUrl) 82 | .then(registration => { 83 | registration.onupdatefound = () => { 84 | const installingWorker = registration.installing; 85 | installingWorker.onstatechange = () => { 86 | if (installingWorker.state === "installed") { 87 | if (navigator.serviceWorker.controller) { 88 | // At this point, the old content will have been purged and 89 | // the fresh content will have been added to the cache. 90 | // It's the perfect time to display a "New content is 91 | // available; please refresh." message in your web app. 92 | let event = new CustomEvent("serviceWorkerNotification", { 93 | detail: { 94 | state: "new" 95 | } 96 | }); 97 | window.document.dispatchEvent(event); 98 | console.log("New content is available; please refresh."); 99 | } else { 100 | // At this point, everything has been precached. 101 | // It's the perfect time to display a 102 | // "Content is cached for offline use." message. 103 | let event = new CustomEvent("serviceWorkerNotification", { 104 | detail: { 105 | state: "cached" 106 | } 107 | }); 108 | window.document.dispatchEvent(event); 109 | console.log("Content is cached for offline use."); 110 | } 111 | } 112 | }; 113 | }; 114 | }) 115 | .catch(error => { 116 | console.error("Error during service worker registration:", error); 117 | }); 118 | } 119 | 120 | function checkValidServiceWorker(swUrl) { 121 | // Check if the service worker can be found. If it can't reload the page. 122 | fetch(swUrl) 123 | .then(response => { 124 | // Ensure service worker exists, and that we really are getting a JS file. 125 | if ( 126 | response.status === 404 || 127 | response.headers.get("content-type").indexOf("javascript") === -1 128 | ) { 129 | // No service worker found. Probably a different app. Reload the page. 130 | navigator.serviceWorker.ready.then(registration => { 131 | registration.unregister().then(() => { 132 | window.location.reload(); 133 | }); 134 | }); 135 | } else { 136 | // Service worker found. Proceed as normal. 137 | registerValidSW(swUrl); 138 | } 139 | }) 140 | .catch(() => { 141 | console.log( 142 | "No internet connection found. App is running in offline mode." 143 | ); 144 | }); 145 | } 146 | 147 | export function unregister() { 148 | if ("serviceWorker" in navigator) { 149 | navigator.serviceWorker.ready.then(registration => { 150 | registration.unregister(); 151 | }); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /public/api/countryCodes.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": "https://gist.github.com/keeguon/2310008", 3 | "countryCodes": [{ 4 | "country_code": "AF", 5 | "country_name": "Afghanistan", 6 | "dialling_code": "+93" 7 | }, 8 | { 9 | "country_code": "AL", 10 | "country_name": "Albania", 11 | "dialling_code": "+355" 12 | }, 13 | { 14 | "country_code": "DZ", 15 | "country_name": "Algeria", 16 | "dialling_code": "+213" 17 | }, 18 | { 19 | "country_code": "AS", 20 | "country_name": "American Samoa", 21 | "dialling_code": "+1" 22 | }, 23 | { 24 | "country_code": "AD", 25 | "country_name": "Andorra", 26 | "dialling_code": "+376" 27 | }, 28 | { 29 | "country_code": "AO", 30 | "country_name": "Angola", 31 | "dialling_code": "+244" 32 | }, 33 | { 34 | "country_code": "AG", 35 | "country_name": "Antigua", 36 | "dialling_code": "+1" 37 | }, 38 | { 39 | "country_code": "AR", 40 | "country_name": "Argentina", 41 | "dialling_code": "+54" 42 | }, 43 | { 44 | "country_code": "AM", 45 | "country_name": "Armenia", 46 | "dialling_code": "+374" 47 | }, 48 | { 49 | "country_code": "AW", 50 | "country_name": "Aruba", 51 | "dialling_code": "+297" 52 | }, 53 | { 54 | "country_code": "AU", 55 | "country_name": "Australia", 56 | "dialling_code": "+61" 57 | }, 58 | { 59 | "country_code": "AI", 60 | "country_name": "Austria", 61 | "dialling_code": "+43" 62 | }, 63 | { 64 | "country_code": "AZ", 65 | "country_name": "Azerbaijan", 66 | "dialling_code": "+994" 67 | }, 68 | { 69 | "country_code": "BH", 70 | "country_name": "Bahrain", 71 | "dialling_code": "+973" 72 | }, 73 | { 74 | "country_code": "BD", 75 | "country_name": "Bangladesh", 76 | "dialling_code": "+880" 77 | }, 78 | { 79 | "country_code": "BB", 80 | "country_name": "Barbados", 81 | "dialling_code": "+1" 82 | }, 83 | { 84 | "country_code": "BY", 85 | "country_name": "Belarus", 86 | "dialling_code": "+375" 87 | }, 88 | { 89 | "country_code": "BE", 90 | "country_name": "Belgium", 91 | "dialling_code": "+32" 92 | }, 93 | { 94 | "country_code": "BZ", 95 | "country_name": "Belize", 96 | "dialling_code": "+501" 97 | }, 98 | { 99 | "country_code": "BJ", 100 | "country_name": "Benin", 101 | "dialling_code": "+229" 102 | }, 103 | { 104 | "country_code": "BM", 105 | "country_name": "Bermuda", 106 | "dialling_code": "+1" 107 | }, 108 | { 109 | "country_code": "BT", 110 | "country_name": "Bhutan", 111 | "dialling_code": "+975" 112 | }, 113 | { 114 | "country_code": "BO", 115 | "country_name": "Bolivia", 116 | "dialling_code": "+591" 117 | }, 118 | { 119 | "country_code": "BA", 120 | "country_name": "Bosnia and Herzegovina", 121 | "dialling_code": "+387" 122 | }, 123 | { 124 | "country_code": "BW", 125 | "country_name": "Botswana", 126 | "dialling_code": "+267" 127 | }, 128 | { 129 | "country_code": "BR", 130 | "country_name": "Brazil", 131 | "dialling_code": "+55" 132 | }, 133 | { 134 | "country_code": "IO", 135 | "country_name": "British Indian Ocean Territory", 136 | "dialling_code": "+246" 137 | }, 138 | { 139 | "country_code": "VG", 140 | "country_name": "British Virgin Islands", 141 | "dialling_code": "+1" 142 | }, 143 | { 144 | "country_code": "BN", 145 | "country_name": "Brunei", 146 | "dialling_code": "+673" 147 | }, 148 | { 149 | "country_code": "BG", 150 | "country_name": "Bulgaria", 151 | "dialling_code": "+359" 152 | }, 153 | { 154 | "country_code": "BF", 155 | "country_name": "Burkina Faso", 156 | "dialling_code": "+226" 157 | }, 158 | { 159 | "country_code": "MM", 160 | "country_name": "Burma Myanmar", 161 | "dialling_code": "+95" 162 | }, 163 | { 164 | "country_code": "BI", 165 | "country_name": "Burundi", 166 | "dialling_code": "+257" 167 | }, 168 | { 169 | "country_code": "KH", 170 | "country_name": "Cambodia", 171 | "dialling_code": "+855" 172 | }, 173 | { 174 | "country_code": "CM", 175 | "country_name": "Cameroon", 176 | "dialling_code": "+237" 177 | }, 178 | { 179 | "country_code": "CA", 180 | "country_name": "Canada", 181 | "dialling_code": "+1" 182 | }, 183 | { 184 | "country_code": "CV", 185 | "country_name": "Cape Verde", 186 | "dialling_code": "+238" 187 | }, 188 | { 189 | "country_code": "KY", 190 | "country_name": "Cayman Islands", 191 | "dialling_code": "+1" 192 | }, 193 | { 194 | "country_code": "CF", 195 | "country_name": "Central African Republic", 196 | "dialling_code": "+236" 197 | }, 198 | { 199 | "country_code": "CL", 200 | "country_name": "Chile", 201 | "dialling_code": "+56" 202 | }, 203 | { 204 | "country_code": "CN", 205 | "country_name": "China", 206 | "dialling_code": "+86" 207 | }, 208 | { 209 | "country_code": "CO", 210 | "country_name": "Colombia", 211 | "dialling_code": "+57" 212 | }, 213 | { 214 | "country_code": "KM", 215 | "country_name": "Comoros", 216 | "dialling_code": "+269" 217 | }, 218 | { 219 | "country_code": "CK", 220 | "country_name": "Cook Islands", 221 | "dialling_code": "+682" 222 | }, 223 | { 224 | "country_code": "CR", 225 | "country_name": "Costa Rica", 226 | "dialling_code": "+506" 227 | }, 228 | { 229 | "country_code": "CI", 230 | "country_name": "Côte d'Ivoire", 231 | "dialling_code": "+225" 232 | }, 233 | { 234 | "country_code": "HR", 235 | "country_name": "Croatia", 236 | "dialling_code": "+385" 237 | }, 238 | { 239 | "country_code": "CU", 240 | "country_name": "Cuba", 241 | "dialling_code": "+53" 242 | }, 243 | { 244 | "country_code": "CY", 245 | "country_name": "Cyprus", 246 | "dialling_code": "+357" 247 | }, 248 | { 249 | "country_code": "CZ", 250 | "country_name": "Czech Republic", 251 | "dialling_code": "+420" 252 | }, 253 | { 254 | "country_code": "CD", 255 | "country_name": "Democratic Republic of Congo", 256 | "dialling_code": "+243" 257 | }, 258 | { 259 | "country_code": "DK", 260 | "country_name": "Denmark", 261 | "dialling_code": "+45" 262 | }, 263 | { 264 | "country_code": "DJ", 265 | "country_name": "Djibouti", 266 | "dialling_code": "+253" 267 | }, 268 | { 269 | "country_code": "DM", 270 | "country_name": "Dominica", 271 | "dialling_code": "+1" 272 | }, 273 | { 274 | "country_code": "DO", 275 | "country_name": "Dominican Republic", 276 | "dialling_code": "+1" 277 | }, 278 | { 279 | "country_code": "EC", 280 | "country_name": "Ecuador", 281 | "dialling_code": "+593" 282 | }, 283 | { 284 | "country_code": "EG", 285 | "country_name": "Egypt", 286 | "dialling_code": "+20" 287 | }, 288 | { 289 | "country_code": "SV", 290 | "country_name": "El Salvador", 291 | "dialling_code": "+503" 292 | }, 293 | { 294 | "country_code": "GQ", 295 | "country_name": "Equatorial Guinea", 296 | "dialling_code": "+240" 297 | }, 298 | { 299 | "country_code": "ER", 300 | "country_name": "Eritrea", 301 | "dialling_code": "+291" 302 | }, 303 | { 304 | "country_code": "EE", 305 | "country_name": "Estonia", 306 | "dialling_code": "+372" 307 | }, 308 | { 309 | "country_code": "ET", 310 | "country_name": "Ethiopia", 311 | "dialling_code": "+251" 312 | }, 313 | { 314 | "country_code": "FK", 315 | "country_name": "Falkland Islands", 316 | "dialling_code": "+500" 317 | }, 318 | { 319 | "country_code": "FO", 320 | "country_name": "Faroe Islands", 321 | "dialling_code": "+298" 322 | }, 323 | { 324 | "country_code": "FM", 325 | "country_name": "Federated States of Micronesia", 326 | "dialling_code": "+691" 327 | }, 328 | { 329 | "country_code": "FJ", 330 | "country_name": "Fiji", 331 | "dialling_code": "+679" 332 | }, 333 | { 334 | "country_code": "FI", 335 | "country_name": "Finland", 336 | "dialling_code": "+358" 337 | }, 338 | { 339 | "country_code": "FR", 340 | "country_name": "France", 341 | "dialling_code": "+33" 342 | }, 343 | { 344 | "country_code": "GF", 345 | "country_name": "French Guiana", 346 | "dialling_code": "+594" 347 | }, 348 | { 349 | "country_code": "PF", 350 | "country_name": "French Polynesia", 351 | "dialling_code": "+689" 352 | }, 353 | { 354 | "country_code": "GA", 355 | "country_name": "Gabon", 356 | "dialling_code": "+241" 357 | }, 358 | { 359 | "country_code": "GE", 360 | "country_name": "Georgia", 361 | "dialling_code": "+995" 362 | }, 363 | { 364 | "country_code": "DE", 365 | "country_name": "Germany", 366 | "dialling_code": "+49" 367 | }, 368 | { 369 | "country_code": "GH", 370 | "country_name": "Ghana", 371 | "dialling_code": "+233" 372 | }, 373 | { 374 | "country_code": "GI", 375 | "country_name": "Gibraltar", 376 | "dialling_code": "+350" 377 | }, 378 | { 379 | "country_code": "GR", 380 | "country_name": "Greece", 381 | "dialling_code": "+30" 382 | }, 383 | { 384 | "country_code": "GL", 385 | "country_name": "Greenland", 386 | "dialling_code": "+299" 387 | }, 388 | { 389 | "country_code": "GD", 390 | "country_name": "Grenada", 391 | "dialling_code": "+1" 392 | }, 393 | { 394 | "country_code": "GP", 395 | "country_name": "Guadeloupe", 396 | "dialling_code": "+590" 397 | }, 398 | { 399 | "country_code": "GU", 400 | "country_name": "Guam", 401 | "dialling_code": "+1" 402 | }, 403 | { 404 | "country_code": "GT", 405 | "country_name": "Guatemala", 406 | "dialling_code": "+502" 407 | }, 408 | { 409 | "country_code": "GN", 410 | "country_name": "Guinea", 411 | "dialling_code": "+224" 412 | }, 413 | { 414 | "country_code": "GW", 415 | "country_name": "Guinea-Bissau", 416 | "dialling_code": "+245" 417 | }, 418 | { 419 | "country_code": "GY", 420 | "country_name": "Guyana", 421 | "dialling_code": "+592" 422 | }, 423 | { 424 | "country_code": "HT", 425 | "country_name": "Haiti", 426 | "dialling_code": "+509" 427 | }, 428 | { 429 | "country_code": "HN", 430 | "country_name": "Honduras", 431 | "dialling_code": "+504" 432 | }, 433 | { 434 | "country_code": "HK", 435 | "country_name": "Hong Kong", 436 | "dialling_code": "+852" 437 | }, 438 | { 439 | "country_code": "HU", 440 | "country_name": "Hungary", 441 | "dialling_code": "+36" 442 | }, 443 | { 444 | "country_code": "IS", 445 | "country_name": "Iceland", 446 | "dialling_code": "+354" 447 | }, 448 | { 449 | "country_code": "IN", 450 | "country_name": "India", 451 | "dialling_code": "+91" 452 | }, 453 | { 454 | "country_code": "ID", 455 | "country_name": "Indonesia", 456 | "dialling_code": "+62" 457 | }, 458 | { 459 | "country_code": "IR", 460 | "country_name": "Iran", 461 | "dialling_code": "+98" 462 | }, 463 | { 464 | "country_code": "IQ", 465 | "country_name": "Iraq", 466 | "dialling_code": "+964" 467 | }, 468 | { 469 | "country_code": "IE", 470 | "country_name": "Ireland", 471 | "dialling_code": "+353" 472 | }, 473 | { 474 | "country_code": "IL", 475 | "country_name": "Israel", 476 | "dialling_code": "+972" 477 | }, 478 | { 479 | "country_code": "IT", 480 | "country_name": "Italy", 481 | "dialling_code": "+39" 482 | }, 483 | { 484 | "country_code": "JM", 485 | "country_name": "Jamaica", 486 | "dialling_code": "+1" 487 | }, 488 | { 489 | "country_code": "JP", 490 | "country_name": "Japan", 491 | "dialling_code": "+81" 492 | }, 493 | { 494 | "country_code": "JO", 495 | "country_name": "Jordan", 496 | "dialling_code": "+962" 497 | }, 498 | { 499 | "country_code": "KZ", 500 | "country_name": "Kazakhstan", 501 | "dialling_code": "+7" 502 | }, 503 | { 504 | "country_code": "KE", 505 | "country_name": "Kenya", 506 | "dialling_code": "+254" 507 | }, 508 | { 509 | "country_code": "KI", 510 | "country_name": "Kiribati", 511 | "dialling_code": "+686" 512 | }, 513 | { 514 | "country_code": "XK", 515 | "country_name": "Kosovo", 516 | "dialling_code": "+381" 517 | }, 518 | { 519 | "country_code": "KW", 520 | "country_name": "Kuwait", 521 | "dialling_code": "+965" 522 | }, 523 | { 524 | "country_code": "KG", 525 | "country_name": "Kyrgyzstan", 526 | "dialling_code": "+996" 527 | }, 528 | { 529 | "country_code": "LA", 530 | "country_name": "Laos", 531 | "dialling_code": "+856" 532 | }, 533 | { 534 | "country_code": "LV", 535 | "country_name": "Latvia", 536 | "dialling_code": "+371" 537 | }, 538 | { 539 | "country_code": "LB", 540 | "country_name": "Lebanon", 541 | "dialling_code": "+961" 542 | }, 543 | { 544 | "country_code": "LS", 545 | "country_name": "Lesotho", 546 | "dialling_code": "+266" 547 | }, 548 | { 549 | "country_code": "LR", 550 | "country_name": "Liberia", 551 | "dialling_code": "+231" 552 | }, 553 | { 554 | "country_code": "LY", 555 | "country_name": "Libya", 556 | "dialling_code": "+218" 557 | }, 558 | { 559 | "country_code": "LI", 560 | "country_name": "Liechtenstein", 561 | "dialling_code": "+423" 562 | }, 563 | { 564 | "country_code": "LT", 565 | "country_name": "Lithuania", 566 | "dialling_code": "+370" 567 | }, 568 | { 569 | "country_code": "LU", 570 | "country_name": "Luxembourg", 571 | "dialling_code": "+352" 572 | }, 573 | { 574 | "country_code": "MO", 575 | "country_name": "Macau", 576 | "dialling_code": "+853" 577 | }, 578 | { 579 | "country_code": "MK", 580 | "country_name": "Macedonia", 581 | "dialling_code": "+389" 582 | }, 583 | { 584 | "country_code": "MG", 585 | "country_name": "Madagascar", 586 | "dialling_code": "+261" 587 | }, 588 | { 589 | "country_code": "MW", 590 | "country_name": "Malawi", 591 | "dialling_code": "+265" 592 | }, 593 | { 594 | "country_code": "MY", 595 | "country_name": "Malaysia", 596 | "dialling_code": "+60" 597 | }, 598 | { 599 | "country_code": "MV", 600 | "country_name": "Maldives", 601 | "dialling_code": "+960" 602 | }, 603 | { 604 | "country_code": "ML", 605 | "country_name": "Mali", 606 | "dialling_code": "+223" 607 | }, 608 | { 609 | "country_code": "MT", 610 | "country_name": "Malta", 611 | "dialling_code": "+356" 612 | }, 613 | { 614 | "country_code": "MH", 615 | "country_name": "Marshall Islands", 616 | "dialling_code": "+692" 617 | }, 618 | { 619 | "country_code": "MQ", 620 | "country_name": "Martinique", 621 | "dialling_code": "+596" 622 | }, 623 | { 624 | "country_code": "MR", 625 | "country_name": "Mauritania", 626 | "dialling_code": "+222" 627 | }, 628 | { 629 | "country_code": "MU", 630 | "country_name": "Mauritius", 631 | "dialling_code": "+230" 632 | }, 633 | { 634 | "country_code": "YT", 635 | "country_name": "Mayotte", 636 | "dialling_code": "+262" 637 | }, 638 | { 639 | "country_code": "MX", 640 | "country_name": "Mexico", 641 | "dialling_code": "+52" 642 | }, 643 | { 644 | "country_code": "MD", 645 | "country_name": "Moldova", 646 | "dialling_code": "+373" 647 | }, 648 | { 649 | "country_code": "MC", 650 | "country_name": "Monaco", 651 | "dialling_code": "+377" 652 | }, 653 | { 654 | "country_code": "MN", 655 | "country_name": "Mongolia", 656 | "dialling_code": "+976" 657 | }, 658 | { 659 | "country_code": "ME", 660 | "country_name": "Montenegro", 661 | "dialling_code": "+382" 662 | }, 663 | { 664 | "country_code": "MS", 665 | "country_name": "Montserrat", 666 | "dialling_code": "+1" 667 | }, 668 | { 669 | "country_code": "MA", 670 | "country_name": "Morocco", 671 | "dialling_code": "+212" 672 | }, 673 | { 674 | "country_code": "MZ", 675 | "country_name": "Mozambique", 676 | "dialling_code": "+258" 677 | }, 678 | { 679 | "country_code": "NA", 680 | "country_name": "Namibia", 681 | "dialling_code": "+264" 682 | }, 683 | { 684 | "country_code": "NR", 685 | "country_name": "Nauru", 686 | "dialling_code": "+674" 687 | }, 688 | { 689 | "country_code": "NP", 690 | "country_name": "Nepal", 691 | "dialling_code": "+977" 692 | }, 693 | { 694 | "country_code": "NL", 695 | "country_name": "Netherlands", 696 | "dialling_code": "+31" 697 | }, 698 | { 699 | "country_code": "AN", 700 | "country_name": "Netherlands Antilles", 701 | "dialling_code": "+599" 702 | }, 703 | { 704 | "country_code": "NC", 705 | "country_name": "New Caledonia", 706 | "dialling_code": "+687" 707 | }, 708 | { 709 | "country_code": "NZ", 710 | "country_name": "New Zealand", 711 | "dialling_code": "+64" 712 | }, 713 | { 714 | "country_code": "NI", 715 | "country_name": "Nicaragua", 716 | "dialling_code": "+505" 717 | }, 718 | { 719 | "country_code": "NE", 720 | "country_name": "Niger", 721 | "dialling_code": "+227" 722 | }, 723 | { 724 | "country_code": "NG", 725 | "country_name": "Nigeria", 726 | "dialling_code": "+234" 727 | }, 728 | { 729 | "country_code": "NU", 730 | "country_name": "Niue", 731 | "dialling_code": "+683" 732 | }, 733 | { 734 | "country_code": "NF", 735 | "country_name": "Norfolk Island", 736 | "dialling_code": "+672" 737 | }, 738 | { 739 | "country_code": "KP", 740 | "country_name": "North Korea", 741 | "dialling_code": "+850" 742 | }, 743 | { 744 | "country_code": "MP", 745 | "country_name": "Northern Mariana Islands", 746 | "dialling_code": "+1" 747 | }, 748 | { 749 | "country_code": "NO", 750 | "country_name": "Norway", 751 | "dialling_code": "+47" 752 | }, 753 | { 754 | "country_code": "OM", 755 | "country_name": "Oman", 756 | "dialling_code": "+968" 757 | }, 758 | { 759 | "country_code": "PK", 760 | "country_name": "Pakistan", 761 | "dialling_code": "+92" 762 | }, 763 | { 764 | "country_code": "PW", 765 | "country_name": "Palau", 766 | "dialling_code": "+680" 767 | }, 768 | { 769 | "country_code": "PS", 770 | "country_name": "Palestine", 771 | "dialling_code": "+970" 772 | }, 773 | { 774 | "country_code": "PA", 775 | "country_name": "Panama", 776 | "dialling_code": "+507" 777 | }, 778 | { 779 | "country_code": "PG", 780 | "country_name": "Papua New Guinea", 781 | "dialling_code": "+675" 782 | }, 783 | { 784 | "country_code": "PY", 785 | "country_name": "Paraguay", 786 | "dialling_code": "+595" 787 | }, 788 | { 789 | "country_code": "PE", 790 | "country_name": "Peru", 791 | "dialling_code": "+51" 792 | }, 793 | { 794 | "country_code": "PH", 795 | "country_name": "Philippines", 796 | "dialling_code": "+63" 797 | }, 798 | { 799 | "country_code": "PL", 800 | "country_name": "Poland", 801 | "dialling_code": "+48" 802 | }, 803 | { 804 | "country_code": "PT", 805 | "country_name": "Portugal", 806 | "dialling_code": "+351" 807 | }, 808 | { 809 | "country_code": "PR", 810 | "country_name": "Puerto Rico", 811 | "dialling_code": "+1" 812 | }, 813 | { 814 | "country_code": "QA", 815 | "country_name": "Qatar", 816 | "dialling_code": "+974" 817 | }, 818 | { 819 | "country_code": "CG", 820 | "country_name": "Republic of the Congo", 821 | "dialling_code": "+242" 822 | }, 823 | { 824 | "country_code": "RE", 825 | "country_name": "Réunion", 826 | "dialling_code": "+262" 827 | }, 828 | { 829 | "country_code": "RO", 830 | "country_name": "Romania", 831 | "dialling_code": "+40" 832 | }, 833 | { 834 | "country_code": "RU", 835 | "country_name": "Russia", 836 | "dialling_code": "+7" 837 | }, 838 | { 839 | "country_code": "RW", 840 | "country_name": "Rwanda", 841 | "dialling_code": "+250" 842 | }, 843 | { 844 | "country_code": "BL", 845 | "country_name": "Saint Barthélemy", 846 | "dialling_code": "+590" 847 | }, 848 | { 849 | "country_code": "SH", 850 | "country_name": "Saint Helena", 851 | "dialling_code": "+290" 852 | }, 853 | { 854 | "country_code": "KN", 855 | "country_name": "Saint Kitts and Nevis", 856 | "dialling_code": "+1" 857 | }, 858 | { 859 | "country_code": "MF", 860 | "country_name": "Saint Martin", 861 | "dialling_code": "+590" 862 | }, 863 | { 864 | "country_code": "PM", 865 | "country_name": "Saint Pierre and Miquelon", 866 | "dialling_code": "+508" 867 | }, 868 | { 869 | "country_code": "VC", 870 | "country_name": "Saint Vincent and the Grenadines", 871 | "dialling_code": "+1" 872 | }, 873 | { 874 | "country_code": "WS", 875 | "country_name": "Samoa", 876 | "dialling_code": "+685" 877 | }, 878 | { 879 | "country_code": "SM", 880 | "country_name": "San Marino", 881 | "dialling_code": "+378" 882 | }, 883 | { 884 | "country_code": "ST", 885 | "country_name": "São Tomé and Príncipe", 886 | "dialling_code": "+239" 887 | }, 888 | { 889 | "country_code": "SA", 890 | "country_name": "Saudi Arabia", 891 | "dialling_code": "+966" 892 | }, 893 | { 894 | "country_code": "SN", 895 | "country_name": "Senegal", 896 | "dialling_code": "+221" 897 | }, 898 | { 899 | "country_code": "RS", 900 | "country_name": "Serbia", 901 | "dialling_code": "+381" 902 | }, 903 | { 904 | "country_code": "SC", 905 | "country_name": "Seychelles", 906 | "dialling_code": "+248" 907 | }, 908 | { 909 | "country_code": "SL", 910 | "country_name": "Sierra Leone", 911 | "dialling_code": "+232" 912 | }, 913 | { 914 | "country_code": "SG", 915 | "country_name": "Singapore", 916 | "dialling_code": "+65" 917 | }, 918 | { 919 | "country_code": "SK", 920 | "country_name": "Slovakia", 921 | "dialling_code": "+421" 922 | }, 923 | { 924 | "country_code": "SI", 925 | "country_name": "Slovenia", 926 | "dialling_code": "+386" 927 | }, 928 | { 929 | "country_code": "SB", 930 | "country_name": "Solomon Islands", 931 | "dialling_code": "+677" 932 | }, 933 | { 934 | "country_code": "SO", 935 | "country_name": "Somalia", 936 | "dialling_code": "+252" 937 | }, 938 | { 939 | "country_code": "ZA", 940 | "country_name": "South Africa", 941 | "dialling_code": "+27" 942 | }, 943 | { 944 | "country_code": "KR", 945 | "country_name": "South Korea", 946 | "dialling_code": "+82" 947 | }, 948 | { 949 | "country_code": "ES", 950 | "country_name": "Spain", 951 | "dialling_code": "+34" 952 | }, 953 | { 954 | "country_code": "LK", 955 | "country_name": "Sri Lanka", 956 | "dialling_code": "+94" 957 | }, 958 | { 959 | "country_code": "LC", 960 | "country_name": "St. Lucia", 961 | "dialling_code": "+1" 962 | }, 963 | { 964 | "country_code": "SD", 965 | "country_name": "Sudan", 966 | "dialling_code": "+249" 967 | }, 968 | { 969 | "country_code": "SR", 970 | "country_name": "Suriname", 971 | "dialling_code": "+597" 972 | }, 973 | { 974 | "country_code": "SZ", 975 | "country_name": "Swaziland", 976 | "dialling_code": "+268" 977 | }, 978 | { 979 | "country_code": "SE", 980 | "country_name": "Sweden", 981 | "dialling_code": "+46" 982 | }, 983 | { 984 | "country_code": "CH", 985 | "country_name": "Switzerland", 986 | "dialling_code": "+41" 987 | }, 988 | { 989 | "country_code": "SY", 990 | "country_name": "Syria", 991 | "dialling_code": "+963" 992 | }, 993 | { 994 | "country_code": "TW", 995 | "country_name": "Taiwan", 996 | "dialling_code": "+886" 997 | }, 998 | { 999 | "country_code": "TJ", 1000 | "country_name": "Tajikistan", 1001 | "dialling_code": "+992" 1002 | }, 1003 | { 1004 | "country_code": "TZ", 1005 | "country_name": "Tanzania", 1006 | "dialling_code": "+255" 1007 | }, 1008 | { 1009 | "country_code": "TH", 1010 | "country_name": "Thailand", 1011 | "dialling_code": "+66" 1012 | }, 1013 | { 1014 | "country_code": "BS", 1015 | "country_name": "The Bahamas", 1016 | "dialling_code": "+1" 1017 | }, 1018 | { 1019 | "country_code": "GM", 1020 | "country_name": "The Gambia", 1021 | "dialling_code": "+220" 1022 | }, 1023 | { 1024 | "country_code": "TL", 1025 | "country_name": "Timor-Leste", 1026 | "dialling_code": "+670" 1027 | }, 1028 | { 1029 | "country_code": "TG", 1030 | "country_name": "Togo", 1031 | "dialling_code": "+228" 1032 | }, 1033 | { 1034 | "country_code": "TK", 1035 | "country_name": "Tokelau", 1036 | "dialling_code": "+690" 1037 | }, 1038 | { 1039 | "country_code": "TO", 1040 | "country_name": "Tonga", 1041 | "dialling_code": "+676" 1042 | }, 1043 | { 1044 | "country_code": "TT", 1045 | "country_name": "Trinidad and Tobago", 1046 | "dialling_code": "+1" 1047 | }, 1048 | { 1049 | "country_code": "TN", 1050 | "country_name": "Tunisia", 1051 | "dialling_code": "+216" 1052 | }, 1053 | { 1054 | "country_code": "TR", 1055 | "country_name": "Turkey", 1056 | "dialling_code": "+90" 1057 | }, 1058 | { 1059 | "country_code": "TM", 1060 | "country_name": "Turkmenistan", 1061 | "dialling_code": "+993" 1062 | }, 1063 | { 1064 | "country_code": "TC", 1065 | "country_name": "Turks and Caicos Islands", 1066 | "dialling_code": "+1" 1067 | }, 1068 | { 1069 | "country_code": "TV", 1070 | "country_name": "Tuvalu", 1071 | "dialling_code": "+688" 1072 | }, 1073 | { 1074 | "country_code": "UG", 1075 | "country_name": "Uganda", 1076 | "dialling_code": "+256" 1077 | }, 1078 | { 1079 | "country_code": "UA", 1080 | "country_name": "Ukraine", 1081 | "dialling_code": "+380" 1082 | }, 1083 | { 1084 | "country_code": "AE", 1085 | "country_name": "United Arab Emirates", 1086 | "dialling_code": "+971" 1087 | }, 1088 | { 1089 | "country_code": "GB", 1090 | "country_name": "United Kingdom", 1091 | "dialling_code": "+44" 1092 | }, 1093 | { 1094 | "country_code": "US", 1095 | "country_name": "United States", 1096 | "dialling_code": "+1" 1097 | }, 1098 | { 1099 | "country_code": "UY", 1100 | "country_name": "Uruguay", 1101 | "dialling_code": "+598" 1102 | }, 1103 | { 1104 | "country_code": "VI", 1105 | "country_name": "US Virgin Islands", 1106 | "dialling_code": "+1" 1107 | }, 1108 | { 1109 | "country_code": "UZ", 1110 | "country_name": "Uzbekistan", 1111 | "dialling_code": "+998" 1112 | }, 1113 | { 1114 | "country_code": "VU", 1115 | "country_name": "Vanuatu", 1116 | "dialling_code": "+678" 1117 | }, 1118 | { 1119 | "country_code": "VA", 1120 | "country_name": "Vatican City", 1121 | "dialling_code": "+39" 1122 | }, 1123 | { 1124 | "country_code": "VE", 1125 | "country_name": "Venezuela", 1126 | "dialling_code": "+58" 1127 | }, 1128 | { 1129 | "country_code": "VN", 1130 | "country_name": "Vietnam", 1131 | "dialling_code": "+84" 1132 | }, 1133 | { 1134 | "country_code": "WF", 1135 | "country_name": "Wallis and Futuna", 1136 | "dialling_code": "+681" 1137 | }, 1138 | { 1139 | "country_code": "YE", 1140 | "country_name": "Yemen", 1141 | "dialling_code": "+967" 1142 | }, 1143 | { 1144 | "country_code": "ZM", 1145 | "country_name": "Zambia", 1146 | "dialling_code": "+260" 1147 | }, 1148 | { 1149 | "country_code": "ZW", 1150 | "country_name": "Zimbabwe", 1151 | "dialling_code": "+263" 1152 | } 1153 | ] 1154 | } 1155 | --------------------------------------------------------------------------------