eliud_core 1.0.16+3 eliud_core: ^1.0.16+3 copied to clipboard
Eliud core
eliud #
Documentation for eliud is under construction. Please be patient.
- Eliud technology is open source technology.
- The technology allows to build apps and/or websites. Today, app content can include photo galleries, pages with videos and images (html), social media, chat with or between members, your shop / shopping cart, photo sliders, documents, and more. A complete list below.
- Eliud is a layer on top of Flutter. Flutter is an open-source UI software development kit created by Google. Flutter allows to develop cross platform applications for iOS, Android and web. Flutter supports Linux, macOS, Windows and Google Fuchsia. This hasn't been tested with eliud packages yet.
- For those who know Worpress: Eliud is to Flutter as Wordpress is to html:
- Html allows you to construct webpages. However, html requires some level of technical knowledge about building webpages.
- Wordpress and many other similar technologies allow people without knowledge of html to build webpages and websites.
- Flutter allows to build websites and apps, or even Windows, Linux, macOS and Google Fuchsia apps. However, Flutter requires programming skills and technical knowledge.
- Eliud allows people without programming skills and technical knowledge to build cross platform apps and websites.
- Html allows you to construct webpages. However, html requires some level of technical knowledge about building webpages.
- Eliud is pluggable technology, allowing developers
- to extend / add functionalities by means of plugins / packages.
- to change look and feel through using styles.
- A website / app built with Eliud consist of its core Eliud package + one or more Eliud plugins. The app is constructed by configuring it. Configuration, images and videos are stored in Firebase database and Firebase storage.
The below steps document the creation of your own android + apple + web app and includes all instructions, all the way to pushing your app into the apple app store, android store and web.
Example Eliud apps #
These are some example apps which demonstrate what eliud can give you. Everything used is open source, part of eliud project.
App | Ios | Android | Web | |
---|---|---|---|---|
Juuwle - An online store for jewels | Juuwle on the App Store | Juuwle on Google Play | https://juuwle.net | |
Minkey - Community making apps online | This type of app is not allowed on apple store | Minkey on Google Play | https://minkey.io | |
Thoma5 - Profile of Thomas. Under construction | In development | In development | https://thoma5.com |
Chapter I. Create a simple "hello world" Android app #
This guide are all steps to create a minimum android, iOS or web app with Eliud.
Whenever this pops up, make note of this for what this is in your case, as you'll need it at some later stage. In the below text we provided this information whilst creating thoma5. Obviously for sensitive information, like passwords, we've provided fake info. |
Step 1: Create a new google account #
- Goto https://www.google.com/account/about/
- Select "Create an account"
- Follow on screen instructions (recommended to use default settings)
|
Step 2: Create a new firebase project #
- Goto https://console.firebase.google.com
- Select "Create a project"
- And follow on screen instructions (recommended to use default settings)
|
Step 3: Configure your project #
- Goto https://console.firebase.google.com
- Select your project
- Select Project Overview > Project settings
- Select support email. Use your google account
Step 4: Setup Firebase database #
-
Select your project
-
Select Build > Firebase database
-
Select "Create database"
-
And follow on screen instructions (recommended to use default settings, start in production mode)
-
With Cloud Firestore open, click on Rules and copy/paste the contents of firestore.rules and publish.
For convenience, and to familiarise yourself with firebase, at this point we copy/paste these rules. However, later we will upload the same rules more efficiently using firestore commands from command line
Step 5: Setup Firebase storage #
-
Select your project
-
Select Build > Storage
-
Select "Get started"
-
And follow on screen instructions (recommended to use default settings, start in production mode)
-
With Storage open, click on Rules and copy/paste the contents of storage.rules and publish.
For convenience, and to familiarise yourself with firebase, at this point we copy/paste these rules. However, later we will upload the same rules more efficiently using firestore commands from command line
-
With storage page open, retrieve your "bucket" from the url. You bucket is the bit in front of ".appspot" in the url. In our case the url is https://console.firebase.google.com/project/thoma5/storage/thoma5.appspot.com/files, hence the bucket is thoma5
|
Step 6: Setup Google Authentication #
- Goto https://console.firebase.google.com
- Select your project
- Select Authentication
- Select Sign-in method
- Select Google from Sign-in providers
- Enable the Google sign-in
Step 7: Generate key #
- Run the following command at command prompt:
keytool -genkey -v -keystore your_keystore_filename -storepass your_keystore_storepass -alias your_keystore_alias -keypass your_keystore_keypass -keyalg RSA -keysize 2048 -validity 36524
-
Then follow onscreen instructions. Then store the key-file in a safe place. You will have to use it multiple times in the future.
-
Now run:
keytool -list -v -alias your_keystore_alias -keystore your_keystore_filename -storepass your_keystore_storepass -keypass your_keystore_keypass
For example:
keytool -genkey -v -keystore %USERPROFILE%\\.android\\thoma5.keystore -storepass abc -alias thoma5key -keypass cde -keyalg RSA -keysize 2048 -validity 36524
keytool -list -v -alias thoma5key -keystore %USERPROFILE%\\.android\\thoma5b.keystore -storepass abc -keypass cde
|
MORE INFO
Step 8: Add Firebase Android App #
- Goto https://console.firebase.google.com
- Select your project
- Click 'Add app' and select platform 'Android'"
- Specify your android package name
- Specify your android app nickname
- Paste the SHA-1 key Your keystore SHA1
- Press "Register app"
- Then download the file google-services.json
|
Step 9: Create Android Studio project #
-
Start Android studio
-
Select File > New > New Flutter Project
-
Specify
- Flutter SDK path and press Next
-
Specify
- Project name: e.g. thoma5_app
- Project location: e.g. C:\src\apps\thoma5_app
- Description: e.g. Thoma5 app
- Project type: Should be "Application"
- Organization: e.g. com.thoma5
- Android language: Should be Java
- iOS language: Should be Swift
- Platforms: Should be Android, iOS and Web
❗ IMPORTANT ❗
The android package name specified as Your Android app package name - e.g. com.thoma5.thoma5_app - should be equal to the concatenation of organisation - e.g. com.thoma5 - a dot and the project_name - e.g. thoma5_app
-
Press finish
|
Step 10: Copy google_services.json #
- Switch to the Project view in Android Studio to see your project root directory.
- Move your downloaded google-services.json file into your module (app-level) root directory, e.g. thoma5_app/android/app
Step 11: Apply firebase SDK instructions #
- Goto https://console.firebase.google.com
- Select your project
- Find your app from "your apps" section, then press "See SDK instructions"
- You get to chance to re-download the google_services.json file, skip this by pressing next.
- Now apply the suggestions provided. Make sure to select Groovy (build.gradle) and Java.
At the time of writing this document, the changes to make were:
file | location | add |
---|---|---|
(1) thoma5_app/android/build.gradle | buildscripts > dependencies | classpath 'com.google.gms:google-services:4.3.15' |
(2) thoma5_app/android/app/build.gradle | plugins | id 'com.google.gms.google-services' |
(3) Finally the below at the bottom of thoma5_app/android/app/build.gradle had to be added
dependencies {
// Import the Firebase BoM
implementation platform('com.google.firebase:firebase-bom:32.2.2')
implementation 'com.google.firebase:firebase-analytics'
// Add the dependencies for any other desired Firebase products
// https://firebase.google.com/docs/android/setup#available-libraries
}
Step 12: Add key store file to your project #
-
Create key.properties file in your android directory, e.g thoma5/android/key.properties
-
Populate it with the below keys and values as below. Find your values specified before (follow the links)
- storeFile=Your keystore filename
- storePassword=Your keystore storepass
- keyPassword=Your keystore keypass
- keyAlias=Your keystore alias
e.g.
storePassword=abc keyPassword=cde keyAlias=thoma5key storeFile=c:/Users/thomas/.android/thoma5.keystore
-
Add the following lines to your android apps build.gradle file, e.g. thoma5/android/app/build.gradle
- Load the properties
plugins { ... } // add this after plugins def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) } // the rest of the file ...
- Use the keystore for signinConfigs
android { defaultConfig { ... } // add this after defaultConfig and before buildTypes signingConfigs { release { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null storePassword keystoreProperties['storePassword'] } } buildTypes { ... } }
- Make sure your buildTypes is pointing to the releasing signingConfigs for both debug and release builds
buildTypes { release { signingConfig signingConfigs.release } debug { signingConfig signingConfigs.release debuggable true } }
Step 13: Update pubspec.yaml #
- Update you pubspec.yaml file to reflect the below
---
name: thoma5_app
description: Thoma5
homepage: https://thoma5.com
repository: https://github.com/eliudio/thoma5_app
version: 1.0.0
environment:
sdk: '>=3.1.0 <4.0.0'
flutter: '>=3.0.0'
dependencies:
flutter:
sdk: flutter
eliud_core: ^1.0.6+1
eliud_pkg_create: ^1.0.7+1
eliud_stl_mona: ^1.0.1+6
dev_dependencies:
flutter_lints: ^2.0.0
flutter:
uses-material-design: true
- run pub get
Step 14: Update main.dart #
- Replace your main.dart with these contents.
import 'package:eliud_core/eliud.dart';
import 'package:eliud_core/style/_default/default_style_family.dart';
import 'package:eliud_core/core_package.dart';
import 'package:eliud_pkg_create/creator_package.dart';
import 'package:eliud_pkg_create/tools/basic_app.dart';
import 'package:eliud_pkg_text/text_package.dart';
import 'package:eliud_stl_mona/mona_stl_package.dart';
import 'package:eliud_pkg_create/creator_decoration.dart';
import 'package:eliud_stl_mona/mona_style_family.dart';
import 'package:flutter/cupertino.dart';
import 'package:firebase_core/firebase_core.dart';
Future<void> main() async {
String APP_ID = "THOMA5_APP";
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
var eliud = Eliud();
try {
eliud.registerPackage(CorePackage.instance());
eliud.registerPackage(TextPackage.instance());
eliud.registerPackage(MonaStlPackage.instance());
eliud.registerPackage(CreatorPackage.instance());
// register decorations, these are only required if you want to be able to change your app through the interface
eliud.registerDecoration(CreatorDecoration());
// register style families
eliud.registerStyleFamily(MonaStyleFamily.instance());
eliud.registerStyleFamily(DefaultStyleFamily.instance());
// finish init
eliud.finalizeInitialisation();
} catch (exception) {
throw Exception("Exception whilst initialising the app");
}
// create the app if it doesn't exist
await BasicApp.checkApp(APP_ID);
// let's go !
eliud.run(APP_ID, false);
}
|
Step 15: Clean up #
- Delete the directory test, which contains widget_test.dart
Step 16: minSdkVersion #
-
Goto your Flutter SDK path, subdirectory packages\flutter_tools\gradle\src\main\groovy and edit the file flutter.groovy and open it
-
Update the value for minSdkVersion to be 21
class FlutterExtension { ... /** Sets the minSdkVersion used by default in Flutter app projects. */ static int minSdkVersion = 21 ... }
❗ REMARK ❗
We only need to make this change to the minSdkVersion for the SDK 1 time, i.e. do not repeat this step for future projects / apps.
Step 17: Run your app #
- Run the app. Because this is the first time your start the app, it will install a basic app.
- When the app asks to choose an account to login, select your google account
- Ones the basic app is created, it will open
Chapter II. Create the webapp and configure firebase #
In the previous steps we've done the foundation to build an app. The next big step is to introduce
- web deployment
- authentication
- functions to support packages
Step 1: Buy domain #
- Buy a domain name, e.g. on squarespace.com.
|
Step 2: Add some basic functionality to your app #
- After you've started your app in the previous step, a "Hello world" screen should appear.
- Press the pen icon to toggle editing mode on.
- Then press the - app button and in the general section
- change the title of your application
- change the home url to your domain url. This is constructed with https:// followed by your domain name
|
- When in edit mode, press the wizard icon to open the wizard dialog box.
- We have only activated a few packages in the code (using eliud.registerPackage), so hence not many wizards are initially available.
- Select signinbutton and press Go!
- Then select signoutbutton and press Go!
Step 3: Logo #
-
create a logo and store into a file in your project directory, e.g. assets/logo/thoma5-logo-1.png
-
add the below to pubspec.yaml
dev_dependencies:
flutter_launcher_icons: ^0.13.1
flutter_icons:
android: launcher_icon
ios: false
image_path: assets/logo/thoma5-logo-1.png
- Run the below from your
flutter pub run flutter_launcher_icons:main
Step 4: Add Firebase Web App #
- Goto https://console.firebase.google.com
- Select your project
- Click 'Add app' and select platform 'Web'"
- Provide an App nickname, e.g. Thoma5
- Select Firebase Hosting.
- Select your project from the drop down box.
- Click on Register app.
- From the "Add Firebase to your web app" page, copy the firebaseConfig details
firebaseConfig |
const firebaseConfig = {
apiKey: "ABcdEfG_H1Ij2KLmNo3PQ_RstUvwXY4Zabcdefg",
authDomain: "thoma5.firebaseapp.com",
projectId: "thoma5",
storageBucket: "thoma5.appspot.com",
messagingSenderId: "263405528229",
appId: "1:123456789012:web:1a2345b6c7890d12ef345h",
measurementId: "G-WL1A23456C"
};
Step 5: Retrieve hosting details #
- Goto https://console.firebase.google.com
- Find the "Add custom domain" button and add
- thoma5.com
- www.thoma5.com, and configure to redirect to thoma5.com
- Make note of the DNS records. We'll need this in a later step.
DNS records | |||||||||||||||||||
Domain: thoma5.com
Domain: www.thoma5.com
|
Step 6: Setup email forwarding #
-
Setup email forwarding
- from info@thoma5.com
- to: your google account
|
Step 7: Subscribe to mailtrap #
- https://mailtrap.io/
- Select sign up
- Select "Use google account" and select your google account
- Select "Email Sending", enter your domain and press "Add Your DomaiN"
- Make note of the DNS records. We'll need this in a later step.
DNS records | ||||||||||||||||||||||||||||||||||||
|
- Click next and in the SMTP/API Settings click API
- Press the "Copy" next to Api Token and keep it somewhere safe. We'll need it soon.
|
Step 8: Setup DNS records for firebase hosting #
Follow the guidelines of your domain registrar to configure your DNS in line with the DNS records specified in the firebase hosting dashboard.
Example 1: domains.google.com #
- Login into your account on https://domains.google.com
- Select "DNS"
- Select "Manage custom records"
- Create new records with the below information, obviously adjusted in line with your DNS records
Host name | Type | TTL | Data |
_acme-challenge | TXT | N/A | aBcdE1FghIj23k4lmnoPqrstUvw5xyZabcdeF6GHiJk |
A | N/A | 123.123.123.123 | |
TXT | N/A | hosting-site=thoma5 | |
www | CNAME | N/A | thoma5.web.app |
Example 2: squarespace.com #
For squarespace, for thoma5.com, this would the be done following these steps:
- Login into your account on https://www.squarespace.com/
- Select your domain from your domains and select "Manage domain settings"
- Edit DNS
- Add the below records, obviously adjusted in line with your DNS records
Host | Type | Priority | Data |
_acme-challenge | TXT | N/A | aBcdE1FghIj23k4lmnoPqrstUvw5xyZabcdeF6GHiJk |
@ | A | N/A | 123.123.123.123 |
@ | TXT | N/A | hosting-site=thoma5 |
www | CNAME | N/A | thoma5.web.app |
MORE INFO
Step 9: Setup DNS records for mailtrap #
Follow the guidelines of your domain registrar to configure your DNS in line with the DNS records specified in the mailtrap dashboard.
Example 1: domains.google.com #
- Login into your account on https://domains.google.com
- Select "DNS"
- Select "Manage custom records"
- Create new records with the below information, obviously adjusted with your DNS records
Host name/td> | Type | TTL | Data |
1abcdef2g34hijkl | CNAME | 3600 | smtp.mailtrap.live |
TXT | 3600 | v=spf1 include:_spf.smtp.mailtrap.live ~all | |
rwmt1._domainkey | CNAME | 3600 | rwmt1.dkim.smtp.mailtrap.live |
rwmt2._domainkey | CNAME | 3600 | rwmt2.dkim.smtp.mailtrap.live |
_dmarc | TXT | 3600 | v=DMARC1; p=none; rua=mailto:dmarc@smtp.mailtrap.live; ruf=mailto:dmarc@smtp.mailtrap.live; rf=afrf; pct=100 |
mt-link | CNAME | 3600 | t.mailtrap.live |
Example 2: squarespace.com #
For squarespace, for thoma5.com, this would the be done following these steps:
- Login into your account on https://www.squarespace.com/
- Select your domain from your domains and select "Manage domain settings"
- Edit DNS
- Add the below records, obviously adjusted in line with your DNS records
Host | Type | Priority | Data |
1abcdef2g34hijkl | CNAME | 3600 | smtp.mailtrap.live |
@ | TXT | 3600 | v=spf1 include:_spf.smtp.mailtrap.live ~all |
rwmt1._domainkey | CNAME | 3600 | rwmt1.dkim.smtp.mailtrap.live |
rwmt2._domainkey | CNAME | 3600 | rwmt2.dkim.smtp.mailtrap.live |
_dmarc | TXT | 3600 | v=DMARC1; p=none; rua=mailto:dmarc@smtp.mailtrap.live; ruf=mailto:dmarc@smtp.mailtrap.live; rf=afrf; pct=100 |
mt-link | CNAME | 3600 | t.mailtrap.live |
MORE INFO
Step 10: Verify mailtrap setup #
- Goto mailtrap.io and sign in with your google account
- From your dashboard, select Email Sending, then Sending Domains
- In the domain verification, select Verify all to verify if you've setup your DNS records correctly
- Follow the steps in Verify Setup, i.e. you'll have to answer some security questions to prove you're building a legit app. In our experience this has been a straightforward process. Questions:
- Describe business / project
- Website
- Linked in profile
- What type of emails do you plan to send?
- How do you get the list of recipients?
- Amount of emails planning to send / month
Step 11: Update firebase #
In this step we wil be updating / uploading:
- storage rules
- firestore indexes and rules
- functions
We have uploaded rules in previous steps during the quick start. That was to get up and running quickly. The proper way to update rules is by using the firebase command line tools, which we will do in this step.
Step 11.1: Install firebase command line tools #
- Open cmd
- Run npm install -g firebase-tools
Step 11.2: Enable APIs #
- Goto https://cloud.google.com/build/docs/deploying-builds/deploy-firebase
- Click "Enable the APIs"
- Follow on screen instructions
Step 11.3: Enable firebase functions #
- Goto https://console.firebase.google.com
- Select your project
- Select functions
- Press "Get started" and select next
Step 11.4 Update firebase #
- Run the below (change firebase project and storage bucket to yours)
mkdir c:\src\apps\thoma5_app_firebase
cd c:\src\apps\thoma5_app_firebase
git clone https://github.com/eliudio/firebase.git
cd c:\src\apps\thoma5_app_firebase\firebase
firebase logout
firebase login
firebase functions:config:set mailtrap.token=a1bc234d5e6f7890123ghij45678k901 mailtrap.sender.email=info@thoma5.com mailtrap.sender.name=Thoma5 app.appname="Thoma5" app.collectionname="order" app.bucket="thoma5" stripe.secret=lalalala --project "thoma5"
firebase deploy --project thoma5
Where...
mailtrap.token | mailtrap token |
mailtrap.sender.email | info@thoma5.com |
mailtrap.sender.name | Thoma5 |
app.collectionname | order |
app.bucket | storage bucket |
project | firebase project |
❗ NOTES ❗
-
You can use quotes to specify parameters. E.g. You could use sendgrid.apikey="NO KEY"
-
In the rules, indexes and functions we cover ALL packages that currently exist. If you only use some packages, then these obsolete rules, indexes and functions could be considered obsolete. However, they're harmless being there and it's the easiest way to get going.
-
When you require your own functions, we recommend to organise multiple functions as described here: https://firebase.google.com/docs/functions/organize-functions?gen=2nd
Step 12: Enable APIs #
- Enable People API: https://console.developers.google.com/apis/api/people.googleapis.com
Step 13: Configure oauth web client #
- Goto https://console.cloud.google.com/apis/credentials
- Find the OAuth 2.0 Client IDs with name "Web client". If you find more than one, select any, e.g. the first.
- Find the "ADD URI" and add these domains:
- Find "web client" and copy the client ID
- Press SAVE
|
Step 14: Configure Android Studio project for web #
Step 14.1: Update pubspec.yaml #
- Add the below dependency to pubspec.yaml
eliud_pkg_wizards: ^1.0.4
This will result in your pubspec.yaml file to look like:
---
name: thoma5_app
description: Thoma5
homepage: https://thoma5.com
repository: https://github.com/eliudio/thoma5_app
version: 1.0.0
environment:
sdk: '>=3.1.0 <4.0.0'
flutter: '>=3.0.0'
dependencies:
flutter:
sdk: flutter
eliud_core: ^1.0.7
eliud_pkg_create: ^1.0.7+1
eliud_pkg_wizards: ^1.0.4
eliud_stl_mona: ^1.0.1+6
dev_dependencies:
flutter_lints: ^2.0.0
flutter_launcher_icons: ^0.13.1
flutter:
uses-material-design: true
flutter_icons:
android: launcher_icon
ios: false
image_path: assets/logo/thoma5-logo-1.png
- Run pub get
Step 14.2: Update main.dart #
- Add the following imports to main.dart
import 'package:flutter/foundation.dart';
import 'package:eliud_pkg_wizards/wizards_package.dart';
import 'package:eliud_pkg_etc/etc_package.dart';
import 'package:eliud_pkg_medium/medium_package.dart';
import 'package:eliud_pkg_workflow/workflow_package.dart';
- Replace the Firebase.initializeApp() line in your main.dart with the below: Make sure the values for apiKey -> measurementId correspond with your values available from firebaseConfig
if (kIsWeb) {
await Firebase.initializeApp(
options: const FirebaseOptions(
apiKey: "ABcdEfG_H1Ij2KLmNo3PQ_RstUvwXY4Zabcdefg",
authDomain: "thoma5.firebaseapp.com",
projectId: "thoma5",
storageBucket: "thoma5.appspot.com",
messagingSenderId: "263405528229",
appId: "1:123456789012:web:1a2345b6c7890d12ef345h",
measurementId: "G-WL1A23456C"
));
} else {
await Firebase.initializeApp();
}
- Add the following extra eliud-dependencies:
eliud.registerPackage(WizardsPackage.instance());
- So basically your main.dart will look like
import 'package:eliud_core/eliud.dart';
import 'package:eliud_core/style/_default/default_style_family.dart';
import 'package:eliud_core/core_package.dart';
import 'package:eliud_pkg_create/creator_package.dart';
import 'package:eliud_pkg_create/tools/basic_app.dart';
import 'package:eliud_pkg_text/text_package.dart';
import 'package:eliud_stl_mona/mona_stl_package.dart';
import 'package:eliud_pkg_create/creator_decoration.dart';
import 'package:eliud_stl_mona/mona_style_family.dart';
import 'package:flutter/cupertino.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:eliud_pkg_wizards/wizards_package.dart';
import 'package:eliud_pkg_etc/etc_package.dart';
import 'package:eliud_pkg_medium/medium_package.dart';
import 'package:eliud_pkg_workflow/workflow_package.dart';
Future<void> main() async {
String APP_ID = "THOMA5_APP";
WidgetsFlutterBinding.ensureInitialized();
if (kIsWeb) {
await Firebase.initializeApp(
options: const FirebaseOptions(
apiKey: "ABcdEfG_H1Ij2KLmNo3PQ_RstUvwXY4Zabcdefg",
authDomain: "thoma5.firebaseapp.com",
projectId: "thoma5",
storageBucket: "thoma5.appspot.com",
messagingSenderId: "263405528229",
appId: "1:123456789012:web:1a2345b6c7890d12ef345h",
measurementId: "G-WL1A23456C"
));
} else {
await Firebase.initializeApp();
}
var eliud = Eliud();
try {
eliud.registerPackage(CorePackage.instance());
eliud.registerPackage(TextPackage.instance());
eliud.registerPackage(MonaStlPackage.instance());
eliud.registerPackage(CreatorPackage.instance());
eliud.registerPackage(WizardsPackage.instance());
// register decorations, these are only required if you want to be able to change your app through the interface
eliud.registerDecoration(CreatorDecoration());
// register style families
eliud.registerStyleFamily(MonaStyleFamily.instance());
eliud.registerStyleFamily(DefaultStyleFamily.instance());
// finish init
eliud.finalizeInitialisation();
} catch (exception) {
throw Exception("Exception whilst initialising the app");
}
// create the app if it doesn't exist
await BasicApp.checkApp(APP_ID);
// let's go !
eliud.run(APP_ID, false);
}
Step 14.3: Create images and stylesheet #
- Create favicon.png and overwrite the current existing one in the icons directory of your web folder
Create a png 16 x 16 pixels based on your logo.
- Download loading.gif
Download loading.gif and copy into the icons directory of your web folder
- Download styles.css
Download styles.css and copy into the root directory of your web folder
Step 14.4: Update index.html #
- Add the stylesheet
<link rel="stylesheet" type="text/css" href="styles.css">
- Add the Web client ID in metadata
<!== Google sign-in -->
<meta name="google-signin-client_id" content="x-y.apps.googleusercontent.com">
- Add the loading gif
<div id="progress">
</div>
<script>
var img = document.createElement("img");
img.className = "center";
img.src = "icons/loading.gif";
var src = document.getElementById("progress");
src.appendChild(img);
</script>
- Initialise pdfjs
<script src="https://cdn.jsdelivr.net/npm/pdfjs-dist@2.12.313/build/pdf.js" type="text/javascript"></script>
<script type="text/javascript">
pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.12.313/build/pdf.worker.min.js";
pdfRenderOptions = {
cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.12.313/cmaps/',
cMapPacked: true,
}
</script>
-
Review meta data description and name
-
Which results in the below index.html for thoma5
<!DOCTYPE html>
<html>
<head>
<base href="$FLUTTER_BASE_HREF">
<link rel="stylesheet" type="text/css" href="styles.css">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="Thoma5">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Thoma5">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!== Google sign-in -->
<meta name="google-signin-client_id" content="x-y.apps.googleusercontent.com">
<!-- Favicon -->
<link rel="icon" type="image/png" href="icons/favicon.png"/>
<title>Thoma5</title>
<link rel="manifest" href="manifest.json">
<script>
// The value below is injected by flutter build, do not touch.
const serviceWorkerVersion = null;
</script>
<!-- This script adds the flutter initialization JS code -->
<script src="flutter.js" defer></script>
</head>
<body>
<div id="progress">
</div>
<script>
var img = document.createElement("img");
img.className = "center";
img.src = "icons/loading.gif";
var src = document.getElementById("progress");
src.appendChild(img);
</script>
<script src="https://cdn.jsdelivr.net/npm/pdfjs-dist@2.12.313/build/pdf.js" type="text/javascript"></script>
<script type="text/javascript">
pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.12.313/build/pdf.worker.min.js";
pdfRenderOptions = {
cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.12.313/cmaps/',
cMapPacked: true,
}
</script>
<div id="loading"></div>
<script>
window.addEventListener('load', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine().then(function(appRunner) {
appRunner.runApp();
});
}
});
});
</script>
</body>
</html>
Step 15: Cors` #
To allow images to be accessed / copied, we need to configure cors access.
- goto your app root dir
- create the following file cors.json, make sure to use your domain url instead of https://thoma5.com
[
{
"origin": ["https://thoma5.com"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]
- run this command and login with your
gcloud auth login
- run this gsutil command, make sure to replace "thoma5.appspot.com" with your storageBucket which you can find from your firebaseConfig
gsutil cors set cors.json gs://thoma5.appspot.com
MORE INFO
Step 16: Deploy your website #
- Create file firebase.json in your app root directory with these contents
{
"hosting": {
"public": "build/web",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
- From your app root dir, build and deploy your website
flutter build web --release --no-tree-shake-icons
rem flutter build web --web-renderer html --release --no-tree-shake-icons
call firebase login
call firebase deploy --project thoma5
COMMENT
When you make code changes, e.g. add package dependencies then you will need to repeat 2. to make your changes available on the web. In other words: no other steps - e.g. CORS - need to be repeated.
Step 17: Create policies / policy pages #
When publishing apps to the Google Play or Apple App Store, you will need to provide links to privacy policy, terms of service and/or disclaimer. We recommend providing all 3.
For more information, see policies.pdf
To create policies, at this stage, you can choose to use your website or your android app. We're using the web app as we find the interface easier for the below actions. Also, when using the web app we can actually get the URL of the policies easier than with the app.
For each policy, follow these steps:
-
Create a pdf of your policy, then export a jpg for each page and store these files into assets/legal/policy-x-page-b.jpg, ...
-
Open your app. We open thoma5.com
-
Login with your google account
-
Run the policy wizard to create a new policy and accept all default values.
-
Open your left drawer and select "drawer1" button
-
In "Current menu items" find the page you've created in 4 and open details
-
In "General" change the Text and Description, e.g. "Privacy Policy" and confirm the change
-
From the left drawer, open the policy
-
Press the button "page" which you can find at the left center of your page and select "Update page"
-
In general change the Description and Title of the page, e.g. "Privacy Policy"
-
Press the button "policyPresentation" which you can find at the left top of your page
-
Click the AppPolicy and then select the Update button
-
Press the Pages button
-
Delete the existing page and add all the you've saved as jpg files in 1.
-
Construct the url:
- From your web app: open left drawer, select your policy and copy the URL from your browser address bar
- From android app: update the policy page, copy the key from the general section. Now construct the URL:
- Start with https://
- Add your domain name and a slash: thoma5.com/
- Add your APP_ID and a slash: #THOMA5_APP/
- Add the policy page key: 8a75d3fa-d8e9-4ac8-9eb7-851010807502-policy
-
Now repeat for all 3 policies and record the url's
Step 18: Create membership dashboard page #
A membership dashboard page allows members to request the data that your website / app stores of that person and allows to deactivate the account and destroy all data that we keep of this person.
There are many reasons to have a membership dashboard page.
- One is because we want to provide our users the best experience possible. And if they like to leave our site, without leaving a trace, then that's what we offer.
- Second is to be in line with regulations.
- Third is because when uploading the app to android play store, we must provide a link to a page to allow actions
- Run the memberdashboard wizard (from the usual wizard dialog)
- Open the memberdashboard. A dialog (!) for the memberdashboard opens. This means that we don't have a page, but have a dialog.
- Find your dialog ID.
- From your web app: copy the URL from your browser address bar and find the dialog ID after the last occurance of /
- From android app:
- Press the dialog button
- Find the key from General section Here ecd648b7-68a6-4ebb-94b1-d2211c2f7b8f-member_dashboard
- Run the welcome wizard and create a (blank) page. This page should not be accessible from any menu, i.e. deselect AppBar, Home menu and left and right drawer, but select "Available". The page should open after having been created. However, if for some reason you need to find and open it yourself: open "App" from editor mode, select Pages and find the "Welcome" page. Click the menu next to the page and select "Show page".
- Update the page so that it's title is "Membership dashboard" and have empty html contents.
- Copy the key of the page, here 2ffb7c1e-0a84-4f73-bac9-31c57ffb12c4-page
- Now construct the membership URL:
- Start with https://
- Add your domain name and a slash: thoma5.com/
- Add your APP_ID and a slash: #THOMA5_APP/
- Add the membership dashboard page retrieved in step 6, i.e. here 2ffb7c1e-0a84-4f73-bac9-31c57ffb12c4-page
- Add a /
- Add the membership dialog ID, retrieved in step 3, i.e. here ecd648b7-68a6-4ebb-94b1-d2211c2f7b8f-member_dashboard
- You should test this URL. Try testing it from a new browser, after having logged out from your site. A dialog will appear to allow to login, after which that membership dashboard will open.
Step 19: Setup oauth consent #
TODO
https://console.cloud.google.com/apis/credentials/consent
select user type "External" select "create" fill in the details requested:
- provide a logo
- privacy policy will be available from https://[your domain name[/#[app name in code]/privacy_policy-1. In our example: https://juuwle.net/#JUUWLE_APP/privacy_policy-1
- We will make the terms of service available from https://[your domain name[/#[app name in code]/terms_of_service-1. In our example: https://juuwle.net/#JUUWLE_APP/terms_of_service-1
- Add your domain as Authorised domains, here juuwle.net
- Specify developers email address
- Add scopes:
- .../auth/userinfo.email
- .../auth/userinfo.profil Then press the "In production" button and go through the on screen instructions
NOTES: Your app will be available to any user with a Google Account.
You've configured your app in a way that requires verification . To complete verification, you will need to provide:
An official link to your app's Privacy Policy, use #privacy_policy_url A YouTube video showing how you plan to use the Google user data you get from scopes A written explanation telling Google why you need access to sensitive and/or restricted user data All your domains verified in Google Search Console
3.6 You will receive an email "OAuth Verification Request for Project" Follow instructions in the email
Step 20: Start your free google GCP trial 300 USD #
TODO: https://cloud.google.com/free
Chapter III. Create the ios app #
- a brief overview of the current base packages
Step 1: Register as apple developer #
TODO: https://developer.apple.com/programs/enroll/
Step 2: Create or Update an Apple App ID #
TODO: https://developer.apple.com/account/resources/identifiers/list Press '+' Select "App IDs", then select APP Description: Your app name, here Juuwle Explicit bundle ID: Your bundle ID, net.juuwle.juuwleios Enable "Sign in with Apple" Save and register
Step 3: Create an Apple Service ID #
TODO: https://developer.apple.com/account/resources/identifiers/list Press '+' Select "Services IDs" Description: Juuwle Identifier: net.juuwle.juuwleservice And click register After registering, we'll need to enable sign-in. We'll do this in 5.4.2
Step 4: Register a Private Key for you apple developer account #
TODO: https://developer.apple.com/account/resources/authkeys/list Press '+' Enable Sign in with Apple Configure Select App ID, created in 4.2 Save Configure Register
Copy the Key ID and press download and save the private key... you'll need these two in 5.4.2
Step 5: Enable Apple sign-in on Firestore #
TODO: Optional, if you want the app to be available on ios Select "Apple" and enable it with the switch "Enable" Specify, from 4. Apple setup Services ID, here net.juuwle.juuwleservice Apple team ID, find "Team ID" from https://developer.apple.com/account/ Key ID, get from 4.2 Private key, get from 4.2 Finally copy the authorisation callback URL to be used in the next step Press save
ALSO: Configure apple authorization callback
https://developer.apple.com/account/resources/identifiers/list/serviceId Find the service you created in 4.3 Enable Sign in with Apple Click Configure Primary App ID: the app ID you created in 4.2 Return URL: The authorisation callback URL you copied from firebase console, mine https://juuwle-b719f.firebaseapp.com/__/auth/handler
Step 6: Register your apple device #
TODO: Register your device https://developer.apple.com/account/resources/devices/list
Step 7: Create Apple firebase app #
TODO: App bundle id: net.juuwle.juuwleios App nickname: Juuwle App Store ID (optional):
Download GoogleService-Info.plist (if you can't find it you can find it from the project settings)
Step 8: Configure the Android Studio project for apple #
TODO: (clone your code on your apple machine) Configure the Android Studio project (created in 5.6.3.1)
Step 1. Run the project. It’ll fail with the error "Your session has expired. Please log in". By running the project, you'll have generated the ios xcode project which we'll open in the next step
Step 2. Signing and Capabilities Open .../juuwle/ios/Runner.xcworkspace
Click Runner top left in explorer, then select TARGETS “Runner”, then select “Signing and Capabilities”. You might have signing certificate errors. In that case, from xcode, press Cmd + , Then goto accounts and sign in Then back in the Signing and Capabilities, select the team
Step 3. Back to Android studio, run the app again. It'll fail with processor incompatibility issues. Goto the ios directory and run: sudo arch -x86_64 gem install ffi arch -x86_64 pod install
Step 9. Update file ios/Podfile and replace #
platform :ios, '11.0' With platform :ios, ’11.0'
Step 10. GoogleService-Info.plist #
You’ll get the error "Firebase has not been correctly initialized. Have you added the "GoogleService-Info.plist" file to the project?”
Open Xcode (important!) and add the GoogleService-Info.plist from 5.8.1 to Runner folder (select Runner/Runner) in xcode, ie drag from downloads folder into xcode Runner (make sure to select “copy items if needed")
Step 11. Add a URL sccheme to your project #
https://developers.google.com/identity/sign-in/ios/start-integrating
basically: grab the REVERSED_CLIENT_ID from your GoogleService-info.plist and add it to ios/Runner/Info.plist like this:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>[com.googleusercontent.apps.YOUR REVERSED_CLIENT_ID]</string>
</array>
</dict>
</array>
Step 12. Add capability "Sign in with apple" #
From Xcode, Runner > Targets > Runner select tab "Signing & Capabilities" Add Capability (+Capability)
Don't forget to select Team
Step 13. Trust #
Run the app. If it doesn’t work, run from Xcode
If you get this error "The operation couldn’t be completed. Unable to launch com.example.x.y.z-icloud.com because it has an invalid code signature, inadequate entitlements or its profile has not been explicitly trusted by the user.” Then on your iPhone/tablet open Settings > General > Device Management > Apple Development: someone@icloud.com then select trust at the top.
Chapter IV. Deploy to android store #
See deploy-to-android-store.txt
Chapter V. Deploy to apple store #
See deploy-to-apple-store.txt
Chapter VI. Extend the app with other packages #
Include extra packages and run wizards. For example, for thoma5 we added: eliud.registerPackage(ChatPackage.instance()); eliud.registerPackage(FeedPackage.instance());
See overview of and links to all currently known packages below.
Chapter VII. Write and integrate your own code / packages #
Appendix A. Overview packages #
The dependencies of a typical app #
A typical app, here Minkey, uses the following dependencies:
links #
Package | Description |
---|---|
eliud_core | This package |
eliud_generator | Eliud generator |
eliud_pkg_apps | Eliud package for creating apps through code, not gui |
eliud_pkg_chat | Eliud chat package |
eliud_pkg_create | Eliud create package |
eliud_pkg_etc | Eliud etc package |
eliud_pkg_feed | Eliud feed package |
eliud_pkg_follow | Eliud follow package |
eliud_pkg_fundamentals | Eliud fundamentals package |
eliud_pkg_medium | Eliud medium package |
eliud_pkg_membership | Eliud membership package |
eliud_pkg_notifications | Eliud notifications package |
eliud_pkg_pay | Eliud pay package |
eliud_pkg_shop | Eliud shop package |
eliud_pkg_text | Eliud text package |
eliud_pkg_wizards | Eliud wizards package |
eliud_pkg_workflow | Eliud workflow package |
eliud_stl_mona | Eliud mona style |