snoBoard
A guided RNA modifications catalog.
Note: this is the repository for the web client of snoBoard.
Key Features • Credits • Do it yourself • Code style guidelines
Key Features
- Visualize RNA modifications data from snoBoard's database
- Represent interaction between guide and target RNAs
- Represent target RNAs secondary structure
- Perform conservation analysis across species
- Visualise sequence alignment
- Perform bases & modifications conservation analysis on the alignment
- Show statistics about the organisms present in the database
- Explore snoBoard's API without leaving the website
Credits
This software uses the following open source packages:
Run locally
Setup
npm install
Create a .env
file, and define the following environment variables:
Variable | Description | Example value |
---|---|---|
VITE_API_URL |
URL of the GraphQL API endpoint | 'https://example.com:4000/graphql' |
VITE_STATIC_URL |
URL where static files can be found (e.g. target secondary structure, sequences...) | 'https://example.com:4000/' |
Develop
npm run dev
Test
# unit testing (Vitest):
npm run test:unit
Build
npm run build
Tooling
VSCodium + Volar (not Vetur) is a recommended setup.
For support of .vue
imports in TS, chose your path and follow the steps below:
1. TypeScript Vue Plugin
Pro: One-time setup
Con: Two TS language services are running in parallel (Codium's default and plugin one), which can impact Codium performances
Install the TypeScript Vue Plugin (Volar), and you're ready to go.
2. Volar "Takeover Mode" (recommended)
Pro: Only one TS language service running
Con: A quick setup is needed for each project
- Disable the built-in TypeScript Extension
- Run
Extensions: Show Built-in Extensions
from VSCode's command palette - Find
TypeScript and JavaScript Language Features
, right click and selectDisable (Workspace)
- Run
- Reload the VSCode window by running
Developer: Reload Window
from the command palette.
Source: https://vuejs.org/guide/typescript/overview.html#volar-takeover-mode
Code style guidelines
Project structure
The project files structure is the following:
📂 snoboard-client
├── ⚙️ package.json (& other config files)
├── 🔑 .env (& env.d.ts)
├── 📄 index.html
├── ⚖️ LICENSE
├── 📁 public
└── 📂 src
├── 📄 App.vue
├── 📄 main.ts
├── 📂 router
│ └── 📄 index.ts
├── 📁 views
├── 📁 layouts
├── 📁 components
├── 📁 composables
├── 📁 utils
├── 📁 services
├── 📁 gql
├── 📁 typings
└── 📁 assets
Description of the files & folders
package.json
& other config files
⚙️ Multiple config files are present at the root of the project to configure the different tools & packages used in the application. The most noticeable one is the usual Node's package.json
(along with npm
's generated package-lock.json
), giving the description of the project (name, version, npm
scripts, dependencies).
Apart from it, we have config files for:
-
ESLint (
eslint.config.cts
, using eslint-plugin-vue) -
Git (
.gitignore
) -
Prettier (
.prettierrc.json
&.prettierignore
) -
GraphQL Codegen (
codegen.ts
) -
PostCSS (
postcss.config.js
) -
Tailwind CSS (
tailwind.config.js
) -
TypeScript (
tsconfig.*.json
) -
Vite (
vite.config.ts
) -
Vitest (
vitest.config.ts
)
.env
& env.d.ts
🔑 The .env
file is not published in the repository and needs to be created and filled by the developer as explained above. It contains the environment variables, which are instance-specific, and works according to the Vite's environment variables specification.
The file env.d.ts
defines TypeScript types which needs to be globally available, thus including the environment variables in the .env
file as described in Vite's documentation.
Describing environment variables in
env.d.ts
won't ensure that those variables will actually be available. The types will be defined, so it won't generate type error when using them, but if the variables are not actually set in.env.
, it will still generate a run-time error because they won't exist.**
index.html
📄 Like in all Vite project, the index.html
file is the entry point of the website, and is located at the root of the project. It will be the file served when requesting the website, and does not normally need to be modified (except e.g. when changing favicon).
public
📂 All content placed in the public
folder will be available as static asset, served as-is at the root path (/
). This is for example appropriate for the website's favicon.
src
📂 The src
folder contains files which will be processed when building the application. Those files are separated in different folder according to their role — except for App.vue
& main.ts
.
An alias defined in Vite configuration allows to use
@
in paths to reference this folder.
App.vue
& main.ts
📄 The main.ts
file is embedded in index.html
. It will thus be the first loaded, and is responsible for importing global assets (like CSS stylesheets), and mainly for creating the Vue application and configuring it (applying plugins, registering global components, creating directives, ...), and then mounting it in index.html
.
The App.vue
file is the root component and the entry point of the Vue application, used by main.ts
to create the app with. Each page of the website will actually display it, and it will be in charge to load a different content given the requested page (using the router, described below).
router/index.ts
📄 This file contains the configuration of the router, which is responsible for displaying the page matching the requested URL (this redirection mechanism is called routing, with each accessible location being a route, defined in this file). It exports a router instance, imported in main.ts
and applied as a plugin of the Vue application.
The routing is then put in practice using RouterView
& RouterLink
components, especially in App.vue
which is basically only a RouterView
.
views
📂 As the name suggests, this folder contains the views of the application, which are meta-components representing a page of the website each. Those components are used in the router configuration, a view being attributed to each route, and so displayed by the RouterView
in App.vue
.
layouts
📂 This folder contains components which are meant to be used as layout for the pages, encapsulating their content. They are usually used at the top-level of a view, and all the view content is placed inside the layout component using a slot. An layout example is the main one (MainLayout.vue
), which consists in the header bar and the footer (which by the way is itself a layout), and is used in almost every view.
components
📂 All the remaining components of the application are placed in this folder.
composables
📂 This folder contains the composables of the application, which are utilities using the Vue's Composition API & reactivity system to provide a stateful logic (i.e. which depends on the current state of the application).
utils
📂 This folder contains all stateless utilities (i.e. not composables), functions, constants which we don't want to define directly in the components (because reused, too large or another good reason).
services
📂 This folder contains the configuration of services used by the application, which are then used in main.ts
in application configuration. For now, this only concern the configuration of the urql client.
gql
📂 This folder contains all which is related to the GraphQL API (except the configuration of the client which is done in 📂 services
). Its structure is the following:
TBD
TBD
typings
📂 This folder contains all the TypeScript types & interfaces which are either not specially linked to a component (so can't be defined in it), to large to fit in, or any good reason.
assets
📂 This folder contains all the assets of the application (CSS stylesheets, images, icons). Its structure is the following:
TBD
TBD usage
Naming conventions
- Base components, i.e. components which does not store application state should start with "Base" prefix (see corresponding Vue.js style guide)
- Views:
- Component which are views (in the
views
folder) should end with
- Component which are views (in the
- Composables:
- Compos
Imports organisation in JS/TS
JS or TS code files - including the <script>
part of Vue's SFCs, should be organised in the following way for how they import other code, which should be done at the top of the file:
/**
* Vue imports
*/
import { ... } from 'vue'
import { ... } from 'vue-router' // Place official Vue ecosystem libs here too.
/**
* Components imports
*/
import ... from 'componentLib/some3PComponent'
import ... from '@/components/someLocalComponent'
import ... from '@/layout/someLayoutComponent'
import ... from '@/views/someViewComponent'
/**
* Composables imports
*/
import ... from '@/composables/useSomeComposable'
import { ... } from '@vueuse/core'
/**
* Other 3rd-party imports
*/
import { ... } from 'lodash-es'
/**
* Stores imports
*/
import { ... } from '@/stores/someStore'
/**
* Types imports
*/
import { type ... } from 'lib/someTypes'
import { type ... } from '@/typings/someTypes'
/**
* Utils imports
*/
import { ... } from '@/utils/someUtil'
/**
* Assets imports
*/
import ... from '@/assets/path/to/asset'
Tailwind classes with Vue
Vue has several ways to define classes, including an object syntax and an array syntax. To deal with Tailwind's classes in a consistent way, the following guidelines should be observed:
- Write predetermined classes inline:
class="class-1 class-2..."
- Write parametrised classes as template literals:
:class="`class-${param} class-${param2}`"
- Write conditioned classes with object syntax if there is only one class for each condition, otherwise use ternary or
&&
::class="{ 'class-1': condition1, // to use template literal as key, enclose it in brackets: [`class-${two}`]: condition2 }" // if more than 1 class/condition: :class="condition ? 'class-1' : 'class-2 class-3'" :class="condition && 'class-1 class-2 class-3'"
- Finally, if several of these forms have to be used, combine them with the array syntax:
:class="[ `class-${param}`, { 'class-2': condition }, condition2 && 'class-3', 'class-4 class-5' ]"
These rules can be applied in kind of a recursive manner, for example when using parametrised class in a conditional one.