Skip to content

Latest commit

 

History

History
975 lines (975 loc) · 38.4 KB

brace.org

File metadata and controls

975 lines (975 loc) · 38.4 KB

Inspiring Adversary

getpocket.com

saved.io

pinterest

raindrop.io

getmemex.com

larder.io

notado.app

bmrk.cc

bmrks.com

bookmarkmanager.com

linkwarden.app

Same Name

brace.io

brace.ai

  • Software to Revolutionize Mortgage Servicing

poc

subdomain names for tags

static files + custom domain + wildcard SSL + CDN

google storage

  • Works like CDN but not good as CDN
  • No support https on custom domain

firebase

  • No support wildcard SSL, only support https on subdomains, no more than 20 subdomains! and need to setup one by one!

google storage + google load balancer + google CDN

  • Require load balancer to work with google CDN
  • $18++ per month

google storage + cloudflare

  • $5++ per month

render.com

  • Too newly startup

netlify

  • Limited usage. If exceed, $45++ per month

google app engine

  • Need wildcard SSL from 3rd party i.e. from cloudflare $5 per month
  • No CDN. Platform tries to distribute across its datacenters
  • Should use standard enviroment for cost saving and scalability

aws cloudfront + s3

s3

  • Create a new bucket with public access
  • Upload files and folders in folder ‘build’ and make them all public
  • At bucket properties, enable static website hosting
    • Index document: index.html
    • Error document: index.html
  • access at http://brace-web.s3-website-us-east-1.amazonaws.com/

certificate manager

cloudfront

ref

web design

consideration

  • color
  • contrast
  • white space
  • visual hierarchy
  • scale
  • simplicity
  • consistency
  • responsiveness

guideline

layout, sizing, spacing, margin, padding, line-height

The 8-Point Grid with 4-point baseline system

font

color, shade, shaddow

refactoring ui
lyft color
  • design.lyft.com/re-approaching-color-9e604ba22c88

design system

protocol.mozilla.org

material.io

primer.style

brand.uber.com

evergreen.segment.com

design.workday.com

thumbprint.design

ant.design

orbit.kiwi

SVG tools

Inkscape

  • For logo design, icon design, illustation design
  • Free

UI/UX tools

Sketch

  • $99 one time
  • Only on Mac

Adobe XD

  • Free with limited features
  • On Mac and Windows only

Figma

founding
  • For web UI and UX
  • Free with limited features
  • Web app
  • Can use instead of Inkscape for simple logos, icons, illustrations
    • Better as no need to import/reimport after edit/update the logo/icon
  • Make logos/icons components so that when change, apply to all linked. And can apply directly to linked item for specific change
  • Components can not published with free plan, need to pay
  • Styles and Components are published to team level, not project level
  • As no shared components, need to do everything in 1 file! logo, illustrations, pages
  • Do everything in 1 file, performance issue?
  • In a file, can have several pages
workflow
  • team -> project -> file -> page
  • 1 file, 4 pages: design system, logo, illustrations, pages
  • Create local styles and local components in design system page
    • color pallete
    • 2 font types: font-head, font-content
    • size
    • weight
    • leading, line height
    • h1-h6
  • Create frames in pages like
    • landing_desktop_pattern1
    • landing_mobile_pattern1
    • landing_android_pattern1
    • landing_ios_pattern1
    • main_desktop_
    • main_mobile_
    • main_android_
    • main_ios_

Color tools

colors.co

colormind.io

Contrast tools

usecontrast.com

webaim.org/resources/contrastchecker

Font tools

fontsinuse.com

klim.co.nz

hanken.co

typewolf.com

Chrome extensions

  • responsive-viewer: chrome.google.com/webstore/detail/responsive-viewer/inmopeiepgfljkpkidclfgbgbmfcennb
  • PixelParallel: chrome.google.com/webstore/detail/pixelparallel-by-htmlburg/iffnoibnepbcloaaagchjonfplimpkob
  • VisBug: chrome.google.com/webstore/detail/visbug/cdockenadnadldjbbgcallicgledbeoc

Free icons

Free illustrations

  • undraw.co
  • humaaans.com

Free images

Inspiration

starter kit

Predifined Tailwind CSS + Free templates

pdkit.co

antforfigma.com ($79)

setproduct.com ($86)

refactoring UI ($149)

tailwindui.com ($249)

css system

bulma

  • Good for use as is

tailwind

  • Customizable
  • Use with create_react_app
    • import ‘./tailwind.css’;
  • ref

misc.

  • debug.css
  • cssstats.com

single web app for every page

pages

  • landing/home page
  • list/delete/add/edit page
  • add via url page

libraries

yarn

  • yarn init

babel

  • yarn add @babel/core @babel/cli @babel/preset-env @babel/preset-react –dev
  • create .babelrc at the project root

webpack

  • yarn add webpack webpack-cli webpack-dev-server style-loader css-loader babel-loader –dev
  • create webpack.config.js at the project root

react

sass/scss + bulma

ref

  • blog.usejournal.com/creating-a-react-app-from-scratch-f3c693b84658

starter-kits

create-react-app

gaia & sync

founding

  • some sync requires implementation on both client and server i.e. synceddb (github.com/paldepind/synceddb), pouchdb (pouchdb.com), turtleDB (turtle-db.github.io)
  • manual sync is cumbersum
    • https://github.com/smebberson/array-sync - every time compare needs to load all items
    • keep timestamp at client and keep log files of changes at gaia, max log files might be 10, compare tiemstamps and apply changes, update changes to gaia (a log file) <- irony?
    • easier with only add and delete? use file names(MD5 of content + created dt + updated dt) for sync
    • load just file names to compare? order is important!
    • for bidirectional sync, how to know it’s delete or add?
    • Too complicate, need CRDTs!
  • if there are thousands items, first time sync would take long time
  • IndexedDB and LocalStorage are temporary, not persistant
  • Most promising would be PouchDB
    • Gaia is wrapped by DownLevel and PouchDB connects to by leveldb -> PouchDB will treat it as local database but actually underneath blockstack API is called
    • Create idb as local database, update to this one and sync to the above one
    • No as required CouchDB! (pouchdb.com/faq.html) for Multiversion concurrency control(MCC) and IndexedDB has a limit!
  • Conflict-free Replicated Data Types (CRDTs)
    • might be too slow to download all change log and build final results
    • the list will keep growing with changes
    • ref: github.com/orbitdb/crdts, github.com/conclave-team/conclave

ref

  • medium.com/@cody_84149/gaia-storage-with-leveldb-37112007e335
  • hackernoon.com/building-conclave-a-decentralized-real-time-collaborative-text-editor-a6ab438fe79f
  • hackernoon.com/turtledb-a-javascript-framework-for-building-offline-first-collaborative-web-apps-7183cd787163

gaia & service worker & indexedDB & Cache API

cache in indexedDB for faster startup

  • Check if there are items in indexedDB, if yes, show these first
  • In the background (might not need service worker), connect to Gaia and load latest items
  • if there is change, update UI with latest items
  • Save ONLY latest items in indexedDB for fast startup only!
  • Cache API might not suitable as the same request would return different response, except static files
  • no need to do this manually because there is stale-while-revalidate

SWR for faster startup

  • github.com/zeit/swr
  • features
    • stale-while-revalidate
    • Focus Revalidation
    • Refetch on Interval
    • Scroll Position Recovery and Pagination
  • check
    • can work with gaia? yes
    • pagination?
    • add/edit/delete apply to cache? force update? force refetch?
  • alternative
    • react-query

background job for add/edit/delete and save results in indexedDB for error handling

  • Save data in indexedDB first
  • Connect to Gaia to update
  • if succeed, clear indexedDB, if not retry
  • Need to be a queue
  • check
    • If add and then edit/delete while still connecting to Gaia?
    • If first error, how to handle next in the queue?
  • should use library i.e. redux-offline

redux-offline for faster startup

redux-offline for add/edit/delete

  • github.com/redux-offline/redux-offline
  • can be used for faster startup too, no need SWR

require appropriate UI

  • loading
  • message

caveat

inconsistency in indexedDB / cache management

  • when first visit
  • when revisit
  • when refresh
  • when add/edit/delete items
  • when load more
  • when scroll down/scroll up

tools

workbox

idb

dexie.org

  • Wrapper for IndexedDB

ref

  • developers.google.com/web
  • serviceworke.rs

for each gaia server, one file per one link. performance issue?

questions

  • each file, json data: url, title, image, web_favicon, just_web_name, beautifed_flag, uuid/guid, created_dt, updated_dt
  • forum.blockstack.org/t/proposal-create-a-document-collection-for-cross-app-data-sharing/9286/2
  • github.com/blockstack/blockstack-collections
  • settings file
  • all notes in a folder named notes, settings.json is in root or another folder
  • should have version.json file?
  • how to set filename? worst case: same account creat a file at the same time on web and mobile?
  • read file one by one, performance issue? one round trip, get everything?

gaia api

  • put file
  • list file names with pagination
  • read file

How to extract web page content?

website analytics

tools

  • usefathom.com/, $14 per month -> too expensive?
  • Google analytics is free but privacy?
  • github.com/PostHog/posthog - self host
  • matomo.org
  • plausible.io
  • mixpanel.com

monorepo

  • webapp, firefox extension, chrome extension, android with react native, ios with react native

CI/CD

Github actions

test

This and CI/CD are very important!

tools

  • github.com/enzymejs/enzyme
  • browserstack.com
  • lambdatest.com
  • pact.io
  • browsersync.io
  • developers.google.com/web/tools/lighthouse
  • cypress.io - a complete end-to-end testing experience
  • jest

tools

  • jdenticon.com - generate a random image placeholder for a missing image
  • greensock.com - animation, not totally free
  • relay.dev - the production-ready GraphQL client for React
  • immortalDB - redundant store data in indexedDB, localStorage, and cookies
  • reqres.in - test your front-end against a real API
  • puppeteer - provides a high-level API to control headless Chrome

resources

  • github.com/pujolchr/aStackToRead
  • github.com/ShafiqShams/reacttodosapp
  • github.com/bingex/react-crud
  • github.com/khanshamim/react-application
  • github.com/donovantc/react-shared
  • github.com/ksholla20/react-native-react-monorepo-starter

react native

blockstack-native

requirements

  • sign up, sign in, sign out
  • listFiles, getFile, putFile, deleteFile

tailwindcss for react-native

requirements

  • width query: default, sm, md, lg,
  • custom classnames

auto responsive grid layout

requirements

  • 1 col, 2 cols, 3 cols
  • animation on add, remove
  • render on the fly like flatlist

share extension

requirements

  • share url to and save in a background

change list names

popup with back press

animation

requirement

Add link

List views, view more

Click to visit, Copy link, share link, delete link

search/filter with regex pattern

Getting started screen guide

Extensions on firefox, chrome

Mobile apps - react native

Beautify - extract web page title, images

Trash - 30 days before delete

tagging/labelling/archieved

design user experience (UI/UX)

theme

  • minimalism
    • youtu.be/fzwOBOjSto8?t=224
    • redstapler.co/web-design-trends-2019/
    • youtube.com/watch?v=z0GChBEw4BU
    • kaycinho.com/website-trends-2019-web-design/

inspiration

logo

color

  • black/white/silver/grey: balance, neutral, calm i.e. Apple, Nike, Puma, Honda, Wiki, CartoonNetwork, Benz, wsj, gucci, channel, prada, nytimes.com, sony, uber, medium.com

fonts for brandname

icon

illustration

  • undraw.co/search -> collecting
  • undraw.co/search -> bookmarks

color pallete

  • All black on logo and landing page, colorfy with moving shapes like upperquad.com
  • On landing page requires black-white illustrator
  • On main page, primary color is blue like pros.com and dark shade is like Blockstack color, others generate from colormind.io
  • tailwind css
  • lyft colors
  • brand.uber.com/guide#color-specialty-colors
  • Action color: dark grey (close to black)

font

layout

attributes

  • display-type/position-type
  • margin/padding
  • width/height
  • color
  • font-size
  • font-color
  • font-weight
  • line-height
  • letter-spacing
  • border-size
  • border-color
  • corner-radius

landing page

nav

  • BRACE

1st section

  • Save links to visit later
  • Blockstack login/signup button
  • illustrator

2nd section

  • Easy ways to save
  • 1. click add bottom
  • 2. type brace.to/ at url bar

3rd section

  • All in one place
  • Show main page with beautiful contents

4th section

  • Privacy, your own identity and full control of you data

5th section

  • Start saving now!
  • Blockstack login/signup button

footer

  • twitter, github
  • about, terms of service, privacy
  • faq
    • How different from pocket?
    • What are the benefits of using Brace?

main page

Auto Responsive Grid Layout

  • github.com/xudafeng/autoresponsive-react
  • github.com/tsuyoshiwada/react-stack-grid
  • github.com/dantrain/react-stonecutter

main page w/o items

tutorial

-

Implementation

project

create-react-app

  • medium.com/@xijo/create-react-app-with-tailwind-via-postcss-plus-purgecss-5c36b4c33ba7

dependencies

  • tailwindcss
  • postcss-cli
  • autoprefixer
  • purgecss
  • react
  • react-dom
  • react-scripts
    • webpack
    • babel
    • postcss
    • autoprefixer
    • workbox
  • redux
  • react-redux
  • axios
  • redux-thunk
  • (No use redux-form for more control over action and reducer)
  • redux-offline
  • (No use router for more customization)
  • (No use context as use redux)
  • ? hook ?
  • blockstack-js
  • blockstack-connect
  • url-parse

React

entry point

  • index.js

components

  • App.js
  • Loading.js
  • Landing.js
  • TopBar.js
    • redux-form on search and add
  • BottomBar.js
  • CardList.js
  • CardItem.js
  • Settings.js
  • Adding.js
  • DialogBox.js (Modal.js)
  • Popup.js
    • If use redux, there will be only one popup, but how to click outside to close?
  • Link.js

router

  • switch (medium.com/@daveford/react-router-alternative-switch-acd7961f08db)
  • if switch is not ok, use router5 (life.wongnai.com/router5-39d97bd9e48d)

Redux & Redux-Offline

state

  • link
    • version
    • id (UUID)
    • url (+ domain_name)
    • No need -> list_name: default, archive
    • added_dt
    • did_beautify
    • title
    • favicon
    • screenshot
    • beautified_dt
    • No need -> did_remove
    • No need -> removed_dt
  • links: {key is link id, value is an object of its values}, sort?
    • MyList ~ adding ~ added ~ removing
    • Trash ~ adding ~ added ~ removing
    • Archieve ~ adding ~ added ~ removing

actions

  • SIGN_IN
  • SIGN_OUT

reducers

  • userReducer

Workbox

Blockstack (js, Gaia, connect)

sign in

sign out

fetch with pagination. sort?

  • featch all file with listFiles
  • save all files in root path both links and settings so that when calling listFiles, all files come at once

save. id?

Auto Responsive Grid Layout

Search

  • lucaongaro.eu/blog/2019/01/30/minisearch-client-side-fulltext-search-engine.html

API server

Google app engine

Puppeteer

steps

  • yarn create react-app bracedotto –template cra-template-pwa
  • yarn add tailwindcss postcss autoprefixer
  • yarn add @tailwindcss/forms @tailwindcss/typography @tailwindcss/aspect-ratio @tailwindcss/line-clamp
  • no need for dev dependencies as this’s not a node app
  • yarn add redux redux-loop react-redux reselect
  • yarn add https://github.com/stxapps/redux-offline#028205cec27dcf1ae05e310fc7e45779ee908949
  • yarn add @stacks/auth @stacks/storage @stacks/wallet-sdk @stacks/connect @stacks/encryption
  • Make sure history works:
    • Address bar i.e. change path, change hash!
    • redirect back i.e. from blockstack or other websites
    • back, forward button
    • button, tag <a> in the app
  • yarn add url-parse
  • Hack for back button
    • Need 2 history states for when press back, the previous state still be our app and can handle in onpopstate
    • Need to provide each history state a number for knowing back press or forward press or tag <a> click
    • ref: stackoverflow.com/questions/8980255/how-do-i-retrieve-if-the-popstate-event-comes-from-back-or-forward-actions-with/49329267#49329267, medium.com/@subwaymatch/disabling-back-button-in-react-with-react-router-v5-34bb316c99d7
  • yarn add react-graceful-image
  • yarn add axios
  • yarn add file-saver
  • yarn add @welldone-software/why-did-you-render
  • yarn add framer-motion
  • yarn add @types/node @types/react @types/react-dom @types/jest @types/url-parse @types/file-saver
  • yarn add @wewatch/lexorank
  • webpack 5 no longer include polyfills for node.js core modules by default
    • yarn add react-app-rewired
    • call react-app-rewired in package’s scripts
    • create a config-overrides.js file in the root directory
    • install all polyfills: yarn add assert buffer crypto-browserify process stream-browserify util
  • yarn add blueimp-load-image
  • yarn add idb-keyval
  • yarn add jest-diff

attribution

mvp

No extensions yet

  • Put app name on url
  • Go to webapp and add manually

blockstack apis

  • register
  • sign in
  • sign out
  • retrieve all bookmarks
  • create a bookmark
  • delete a bookmark

monorepo

react

  • state, route, view

fully-fledged

todo

  • BottomBar: jumpy when add popup transition with keyboard
  • On mobile, just use div, not GridLayout
    • can use Tailwindcss space-y
    • no animation!
  • Plus sign at the top of the page, what’s about mobile?

features

  • download all
  • delete all
  • delete account
  • create a new list
  • set default list
  • bulk edit
  • empty trash
  • select pattern or extract content
  • sort, rearrange?

webapp, firefox/chrome extensions, android, ios

servers

tailwindcss’s live-server

create-react-app’s webpack dev server

test server

prod

devices

  • Android phone: Firefox, Chrome
  • iphone (emulator): Firefox, Chrome, Safari
  • iPad: Firefox, Chrome, Safari
  • Macbook: Firefox, Chrome, Safari
  • Ubuntu laptop: Firefox, Chrome

react-native

steps

  • npx @react-native-community/cli@latest init Bracedotto –pm npm
  • npm i [email protected] [email protected] [email protected] [email protected]
  • npm i react-native-svg
  • npm i -D react-native-svg-transformer
    • Update metro.config.js to work with .svg
  • npm i url-parse
  • npm i react-native-animated-spinkit react-native-swiper
  • npm i react-native-safe-area-context
  • npm i react-native-keyboard-manager
  • npm i react-native-webview
  • npm i react-native-file-access
  • npm i https://github.com/stxapps/tailwind-rn#96848a8d2c2370e4f5e57a773ace172c4073157d
  • npm i ‘https://gitpkg.now.sh/stxapps/blockstack-react-native/BlockstackSDK?3d5bcd6ea9a17f00c76be5913009f2c02f13b95f
  • npm i https://github.com/stxapps/redux-offline#028205cec27dcf1ae05e310fc7e45779ee908949
  • npm i @react-native-async-storage/async-storage @react-native-community/netinfo
  • npm i @welldone-software/why-did-you-render -D
  • npm i react-native-iap @wewatch/lexorank axios
  • npm i https://github.com/stxapps/react-native-device-time-format#63f4a9158a91c391d67317a489ccfe8ec28a7c84
  • npm i react-native-document-picker react-native-share @react-native-clipboard/clipboard
  • npm i react-native-flag-secure
  • npm i jest-diff
  • npm i react-native-default-preference
  • npm i https://github.com/stxapps/react-native-receive-sharing-intent#d1b4aa9140e0ad28e1a8403814125a733c92172c
  • npm i react-native-system-navigation-bar @vonovak/react-native-theme-control
  • npm uninstall typescript && npm i [email protected] -D
  • npm i react-native-image-crop-picker
  • npm i react-native-modal react-native-popup-menu
  • npm i @d11/react-native-fast-image
  • change minSdkVersion to 28 in ./android/build.gradle
  • Allow CORS access on https://brace.to/manifest.json
  • Set up Android deep linking: reactnative.dev/docs/linking and developer.android.com/training/app-links/deep-linking
  • npx react-native-asset to link assets i.e. fonts
    • medium.com/@mehrankhandev/ultimate-guide-to-use-custom-fonts-in-react-native-77fcdf859cf4
  • ios
    • Edit PodFile: ios target 15.5, pod ‘Blockstack’
    • First time must run: ~ cd ios ~ bundle install ~ bundle exec pod install
    • In Xcode, Bracedotto General -> Target iOS 15.5
    • In AppDelegate.m, moduleName:@”Brace”
    • Select Bracedotto in left pane, new -> swift file and generate header binding
    • Add image assets, update storyboard
    • Targets -> Bracedotto -> Build Settings -> Build Options -> Always embed Swift standard libraries: $(inherited)
  • ios share extension
    • Target Bracedotto -> Info -> URL Types -> URL Schemes: bracedotto
    • Add RCTLinkingManager in AppDelegate.m
    • File -> New -> Target -> Share Extension ~ Save to Brace, Swift
    • Target Save to Brace -> General -> target iOS: 12.0
    • In Info.plist under Save To Brace ~ NSExtension -> NSExtensionAttributes -> NSExtensionActivationRule -> NSExtensionActivationSupportsWebURLWithMaxCount -> Number 1
    • Update ShareViewController.swift
  • Add App groups from targets: Bracedotto and Save to Brace -> Signing & Capabilities
    • group.bracedotto.share
  • CryptoSwift and NVActivityIndicatorView dependency
    • Add the dependency in Podfile with target ‘Save to Brace’
  • Add fonts to Save to Brace
    • Xcode’s sidebar -> Resources, select all fonts
    • Xcode’s rightbar -> Target Membership, select Save to Brace
    • Save to Brace -> Info.plist, add Fonts provided by application
  • Targets -> Bracedotto -> Build Settings -> Packaging -> Product Name: Brace

Debug

Flipper

iOS

  • stackoverflow.com/a/74030603
  • show hidden files: press the “Command” + “Shift” + “.” (period) keys

test cases

  • web, mobile
  • PC, laptop, tablet, phone
  • features
    • Landing, About, Terms, Privacy, Support
    • Sign up, Sign in
    • Main
    • List links, fetch more
    • New link ~ bottom bar, top bar, empty page, share extension
    • move link, delete link ~ bottom bar, top bar
    • Bulk edit: move notes, permanently delete notes
    • Search ~ add new link, move/delete link, bulk edit ~ pin, unpin, move pin
    • List list names, change list name
    • Card, List
    • New list name, edit list name, move list name, delete list name
    • Popups: CardMenu, ConfirmDelete, MoveTo, ListsMenu
    • Settings: account, subscription, data, lists, misc, about
    • Pin, unpin, move pin
    • Custom link’s title & image
    • WHT_MODE, BLK_MODE

brace-server-worker

Cloud Run and no need all below

  • yarn run deploy
  • might need to increase memory
  • Set schedule */30 * * * *

Creat an instance

  • us-central1-a
  • Choose e2-medium (2 vCPU, 4GB memory)
  • Ubuntu 20.04LTS on balanced persistent disk 10 GB
  • Allow full access to all Cloud APIs
  • **Uncheck** Delete boot disk when instance is deleted

Access the instance

  • gcloud compute ssh –zone=us-west1-b brace-worker-002
  • If found WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
    • exit and run the command explained below the warning i.e. ssh-keygen -f ”home/linux.ssh/google_compute_known_hosts” -R “compute.8353753600559446613”

Setup the instance

  • sudo apt update, sudo apt upgrade
  • install nvm, nodejs, yarn
  • git clone https://github.com/stxapps/brace-server-worker.git
  • cd brace-server-worker
  • git pull
  • yarn
  • if puppeteer errors, try stackoverflow.com/questions/66214552/tmp-chromium-error-while-loading-shared-libraries-libnss3-so-cannot-open-sha
    • ldd node_modules/puppeteer/.local-chromium/linux-XXX/chrome-linux/chrome | grep not
  • curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh && sudo bash add-google-cloud-ops-agent-repo.sh –also-install
    • cloud.google.com/stackdriver/docs/solutions/agents/ops-agent/installation

Add a startup script

  • As startup script is executed by root user, need to specify running commands by linux user
  • use ‘sudo -i’ to switch to root user and test the script below
  • startup script in Custom metadata, key: startup-script, value: #! bin/bash sudo -u linux bash -c ‘cd /home/linux/brace-server-worker; mkdir -p ./logs; NOW=$(date +’%Y%m%d%H%M%S’); /home/linux.nvm/versions/node/v16.18.1/bin/node –experimental-specifier-resolution=node src/index.js > “./logs/log_${NOW}.txt” 2>&1; sudo shutdown -h now’
  • Check node version as it’s hard coded!

Schedule the instance

  • IAM
    • Check include Google-provided role grants
    • Edit on [email protected]
    • Add role Compute Instance Admin (v1)
  • Under VM instances, select tab Instance Schedule
    • Name: brace-server-worker-scheduler
    • Region: us-central1
    • Start CRON expression: 0 * * * *
    • Stop CRON expression: 20 * * * * (at least 15 mins apart)
    • Time zone: Indochina Time (ICT)
    • Add the instance to the schedule
  • ref: cloud.google.com/compute/docs/instances/schedule-instance-start-stop

Fix disk full

  • df -k
  • likely it’s snaps: du -h /var/lib/snapd/snaps
  • remove old snap: sudo bash remove-old-snaps.sh
  • ref: itsfoss.com/free-up-space-ubuntu-linux/

Clean up GCloud DataStore

  • Use GCloud console
  • Delete error extracted results
    • select * from ExtractedResult where status = ‘EXTRACT_ERROR’
  • Delete old extracted results
    • select * from ExtractedResult ORDER BY extractedDT

In-App Purchase

Setup in Connect

  • Need to provide a screenshot and description for review
  • Get App-Specific Shared Secret in Features: In-App Purchases tab
  • Sandbox Testers
    • Use an email address that has never been used as an Apple ID or used to purchase iTunes or App Store content. Consider creating a dedicated email address for each sandbox tester.
  • Add server url to URL for App Store Server Notifications in General -> App information -> v2
  • Add a link Terms of Service in the App Description

Setup in XCode

  • Add In-App Purchase capability in Xcode
  • When testing in-app purchases in the sandbox environment, make sure you’re running a development-signed build of your app; production-signed builds use the production environment.

Setup in React Native

  • yarn add react-native-iap (StoreKit original API)
  • Add missingDimensionStrategy ‘store’, ‘play’ in defaultConfig in android/app/build.gradle

Setup in Play console

  • Release to Closed testing: Alpha
  • Add Testers and the license testers
  • Add iap subscription and activate
  • Use same versionCode and versionName as in Closed testing
  • Setup -> API access (account level, both apps can use it)
    • Create a new Google Cloud Project
    • Create new service account, choose Editor for the project access. Allow all permissions for financial data, create new key

Setup in Google Cloud

  • Add pub/sub topic: projects/iap-001/topics/playstore-notifications-bracedotto
    • Justnote can also use this pub/sub topic and the subscriber!
    • Should name just playstore-notifications as can reuse with others!
  • Change to push with the server endpoint, Set the subscriber to never expire
  • Add permission to the topic
  • Add the topic in Play Console -> Brace.to app -> Monetization setup

Setup in iap-server

  • cd Drive/Workspace/iap-server
  • gcloud app create –project=iap-001 –region=us-central
  • assume unchanged: git update-index –assume-unchanged src/appstore-keys.json src/playstore-service-account.json src/paddle-keys.json
  • yarn add googleapis node-apple-receipt-verify
  • Create Application Default Credential (ADC)
    • select project: iap-001, go to IAM & Admin -> Service Accounts -> Select App Engine default service account -> Keys -> Add Key -> Create new Key
    • Move the file to ~/.config/gcloud/legacy_credentials/[email protected]
    • Refer to it in package.json -> scripts -> start-local
    • cloud.google.com/nodejs/docs/reference/datastore/latest/datastore/datastore
    • cloud.google.com/docs/authentication/production#providing_credentials_to_your_application

Test

iOS

XCode (developer.apple.com/documentation/xcode/setting-up-storekit-testing-in-xcode)

  • Create supporter.storekit
  • In Edit Scheme… -> Run -> Options, Storekit Configuration: supporter.storekit
  • Choose Build Configuration: Debug, Debug executable, and localhost in Info.plist
  • Choose supporter.storekit before
    • Test interrupted Purchases by Editor -> Enable Interrupted Purchases
    • Test failed transactions by Editor -> Fail transactions -> SKErrorUnknown
    • Manage Transactions by Debug > StoreKit > Manage Transactions
  • Don’t forget to change Storekit Configuration back to None

Sandbox (help.apple.com/app-store-connect/#/dev7e89e149d)

  • Don’t need to sign out, just run the app in debug mode, when make a purchase, there will a popup to use test user
  • Sign in with test id: [email protected], normal pass + Conf in the popup
  • Manage the test user in Settings -> App Store -> Sandbox account

Android

  • Join a test program
  • Choose approve purchase, or reject purchase in both purchase popup and in subscription management in Google Play App
  • Choose cancel subscription in subscription management in Google Play App