Last updated: 2022-02-27
This is a svelte template designed for bootstrapping small applications used in social and affective science. It's been setup to use the latest development tooling to make coding the app a fast and fun experience. This includes:
- SvelteJS as an intuitive javascript framework for layout and logic
- TailwindCSS for styling
- Firebase for server-less data storage (and real-time updates)
- Netlify for automatic deploying and hosting from github
See the how the app works section below for more details and specifically the code layout section for working with the template.
git clone https://github.com/ejolly/create-svelte-experiment.git yourAppName
cd yourAppName
npm install
- One time Firebase project setup
- Make your first commit and push to a new github repo
- One time Netlify hosting setup
- One time CORS configuration
npm run dev
and navigate tolocalhost:3000
in your browser- Any new pushes to github will automatically be reflected in your live app hosted on Netlify
- Go to firebase console and create a new project
- Don't enable google analytics (unless you really need to)
- Authentication > enable Email/Password sign-in provider
- Firestore Database > create database in production mode and choose closest geographical server location
- Firestore Database > Rules > Change line 5 to only allow authenticated reads and writes:
allow read, write: if request.auth.uid != null
- Firestore Databse > Data > Create a new collection called
participants
and add a document with dummy data - Delete the dummy document by clicking the rightmost 3-vertical dots. You should now have an empty collection called
participants
- Project Overview > Add web-app (name it whatever, dont add Firebase hosting)
- Copy and paste the Firebase configuration into
src/utils.js
- Configure CORS
- Sign-in to Netlify using your github account
- Choose add new site and select your github repo
- Change the publish directory to
dist
- Click the site settings button and change the site name to something you'll remember
- Back in firebase console go to Authentication > Sign-in method and click the Add domain button and paste in the site name (without a trailing
/
orhttps
prefix)
In order to actually make any stored files (i.e. mp3s, videos, etc) accessible by the app you must set the CORS access policy on google cloud:
- Download gsutil
- Unzip it,
cd
into the unzipped folder, and run:install.sh
- Then run
gcloud init
and login with the same google account you used to create your firebase project - Create a file called
cors.json
that contains the following:
[
{
"origin": ["*"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]
- Find your google storage URL which should be something like
gs://yourproject.appspot.com
- Run
gsutil cors set cors.json yourURL
Once the app is built and deployed, only the public
folder gets served from Netlify, which contains a "skeleton" HTML file that gets filled in using the compiled Javascript in bundle.js
along with the styles in bundle.css.
When a user first visits the deployed app, the javascript logic is executed in a "hierarchical" fashion with App.svelte
treated as the "entry-point" or parent-most component. This component includes logic to determine what child components (e.g. pages/
) should be rendered in the app. Therefore you should place additional such pages within the pages/
sub-directory and any UI elements you plan to reuse across pages in the components/
sub-directory
Most of the coding you'll do will take place within the src/
folder. Create new svelte files in src/pages
for different "pages" or states in your experiment the user will experience. Create new svelte files in src/components
for components that you plan to use across multiple pages. Add javascript functions you plan to reuse across the app into src/utils.js
. You can also use this file as a place to define global variables that can be access throughout the app.
The scaffold also has a few special variables made available by Vite that can be useful during development. In particular using import.meta.env.DEV
can be useful to conditionally run code during development vs when the app is deployed live. You can see an example of this in src/components/Footer.svelte
.
All data for each user is stored within a Firebase collection called 'participants'
(configurable in utils.js
) with a separate document per user. Each user document is both used to store data generated during the experiment itself (i.e. responses to trials or questions) as well as additional app state information for a specific user. State information may include things like where in the experiment the user currently is (e.g. consent, debrief, etc) or what trial of an experiment they're currently on.
The benefit of storing this state information alongside a user's responses is that the app can make use of Firestore's real-time data subscription. The general pattern employed throughout the app is subscribing to the most up-to-date version of a user's document and saving it to a Svelte store called userStore
from within App.svelte
. This initial subscription is setup when a user first navigates to the app. Elsewhere in the app, new data is then written to Firebase using the updateUser
function in utils.js
. This ensures that pages and components are guaranteed to automatically have the "freshest" user data as long as they read from the Svelte store (i.e. $userStore.someField
) rather than querying the database directly.
By referencing the currentState
field in the userStore
, App.svelte
will determine what page a user should be seeing from within pages/
automatically thereby showing the correct content to the user. Because the app is serverless, it's good practice to write any values that you want to persist across page refreshes to the database.
For additional details on how to specifically use this app scaffold with Amazon's Mturk see this project instead.
These just provide a record of how this repo was setup from scratch. There's no need to redo these steps manually!
- Bootstrap the app scaffold using Vite:
# Use the Vite app scaffold creator
# Make sure to choose the svelte option during setup
npm init vite@latest
- Setup TailwindCSS:
# Install tailwind and its dependencies
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
# Create a tailwind configuration file
# This will create a tailwind.config.js and postcss.config.js file in the project
npx tailwind init -p
# Edit those config files with the content in this repo
# to make them handle svelte files and directives properly
# also enables Tailwind's new super fast an customizable JIT mode
-
Create and copy in the contents of
svelte.config.js
This tells.svelte
to treat all<style>
tags as<style lang='postcss'>
which properly understands Tailwind directives like@apply
and variants likehover:bg-red-500
-
Create
Tailwind.svelte
with the contents in this project and import it intoApp.svelte
This actually makes tailwind styles globally available throughout the app