# Architecture
Collecticity Dons — plateforme de dons. Cette doc (Collecticidoc) est maintenue par Urbanis Finance.
Clone : [email protected]:collecticity/don.git
Branche de travail : don-stage.
# Mono-repo
| Dossier | Rôle | Port local | Node |
|---|---|---|---|
backend/ | API Express + GraphQL + crons | 3001 | 16 (^16.13.1) |
frontend/ | Site public (Nuxt SSR) | 3000 | 16 |
admin/ | Dashboard admin (Nuxt) | 3002 | 16 |
common/ | Thème, logos (PLATFORM_NAME) | — | — |
docs/ | Ce site VuePress | 8080 en npm run dev | 14.15 au build CC |
Les 3 apps se parlent via APP_URL / API_URL / ADMIN_URL.
Install local : Getting started.
# Staging
Hébergement Clever Cloud. URLs :
| App | URL | Alias CC |
|---|---|---|
| Frontend | https://app-don-stage.collecticity.fr | don-frontend-staging |
| Backend / API | https://api-don-stage.collecticity.fr | don-backend-staging |
| Admin | https://admin-don-stage.collecticity.fr | don-admin-staging |
Variables d’environnement typiques (staging) :
PLATFORM_NAME=CollecticityPAYMENT_SERVICE_PROVIDER=MANGOPAYENV/NODE_ENVselon l’app CCAPP_URL,API_URL= les URLs HTTPS ci-dessus
Déployer une app (depuis la machine, scripts locaux deploy-don.sh) :
cd frontend && sh deploy-don.sh staging # clever deploy -a don-frontend-staging -f
cd backend && sh deploy-don.sh staging
cd admin && sh deploy-don.sh staging
Jenkins (Jenkinsfile) tourne sur les commits ; le déploiement docs n’est pas activé (DEPLOY_DOC=no). La doc se déploie à part (docs/deploy-doc.sh, app don-docs).
# Backend
- Stack : Node 16, Express, Apollo GraphQL, MongoDB, sessions (
express-session+ MongoStore). - Entrée :
backend/bin/start.js— migrations puis serveur, puis crons. - Install : voir Getting started. Commandes :
cd backend && npm install && npm run dev(après.env). - API : un seul endpoint GraphQL
POST /graphql(et playground enNODE_ENV=development:http://localhost:3001/graphql). - Schéma :
backend/graphql/typeDefs/types/Query.graphqletMutation.graphql. - Proxy front : le Nuxt frontend proxy
/graphqlversAPI_URL(frontend/nuxt.config.js).
Le navigateur tape donc https://app-don-stage.collecticity.fr/graphql ; le SSR doit utiliser API_URL (backend).
Webhooks Mangopay : fichiers dans backend/routes/hooks/ (payIn, payOut, transfer, KYC, UBO, …). JSDoc type GET /webhooks/mangopay/payin.
Crons : backend/crons/ — liste dans API reference.
# Frontend (site public)
- Stack : Nuxt 2 (SSR), Vue 2, Vuex, Apollo, Element UI, nuxt-i18n, Stylus.
- Install :
cd frontend && npm install && npm run dev(port 3000). - Config :
frontend/.env—APP_URL,API_URL,PLATFORM_NAME,PAYMENT_SERVICE_PROVIDER,S3_URL(Cellar), recaptcha / GMaps / Intercom, etc. (modèle :frontend/.env.example). - Thème :
common/Collecticity/theme(selonPLATFORM_NAME) + CSS Element généré (npm run element:themessi le thème change).
Parcours donateur : pages contribution / paiement (CB, virement, chèque). Le workflow de création jusqu’à clôture d’une campagne est dans le guide projets.
# Admin
- Stack : Nuxt 2, Apollo, Element UI.
- Install :
cd admin && npm install && npm run dev(port 3002). - Config :
admin/.env—API_URL,APP_URL,PLATFORM_NAME,ADMIN_EMAIL/ADMIN_PASSWORD, PSP. - Login admin : mot de passe
ADMIN_PASSWORDdu.envbackend (création user admin via migration / seed).
# Variables d’environnement (commun)
À coller dans chaque .env concerné :
| Variable | Rôle |
|---|---|
PLATFORM_NAME | Collecticity |
PAYMENT_SERVICE_PROVIDER | MANGOPAY |
APP_URL | Frontend (http://localhost:3000 en local) |
API_URL | Backend (http://localhost:3001) |
ADMIN_URL | Admin (backend surtout) |
MONGODB_URL / MONGODB_DATABASE | Mongo (backend) |
SESSION_SECRET | Sessions backend |
MANGOPAY_* | API sandbox / prod Mangopay |
MAILGUN_* / EMAIL_FROM | E-mails |
CELLAR_ADDON_HOST / CELLAR_ADDON_KEY_ID / CELLAR_ADDON_KEY_SECRET | Cellar (stockage fichiers, backend) |
S3_BUCKET | Nom du bucket Cellar (parfois encore un bucket Amazon) |
S3_URL | URL publique des fichiers (frontend, proxy /s3) |
Ne pas committer les .env (secrets). Copier depuis les .env.example.
# Terminologie
| Terme | Sens |
|---|---|
| Donateur / Contributor | Personne ou organisation qui donne |
| Porteur de projet / Project owner | Organisation qui porte une campagne |
| Contribution / Don | Don (carte, virement ou chèque) |
| Campagne / Collecte | Projet de collecte publique |
# Technologies & services
- Runtime apps : Node.js 16, npm 8
- Front / admin : Nuxt, Vue, Vuex, Apollo, Element UI
- Backend : Express, GraphQL, MongoDB, AJV, ESLint
- Paiement : Mangopay (opens new window)
- E-mail : Mailgun (opens new window)
- Fichiers : Cellar (opens new window) (Clever Cloud, API compatible S3) — c’est le stockage habituel. Amazon S3 reste possible ponctuellement (anciennes URLs / migration). Le client est dans
backend/utils/s3.js(CELLAR_ADDON_*+S3_BUCKET, URLs*.cellar-c2.services.clever-cloud.com). - Hébergement : Clever Cloud (opens new window)
- CI : Jenkins (
Jenkinsfile) - Autres souvent configurés : reCAPTCHA, Google Maps, Intercom, Mailchimp
# Fichiers statiques plateforme
Logos etc. : common/$PLATFORM_NAME/static → servis en $HOST/logo.svg (ex. common/collecticity/static/logo.svg). Cache long (1 an) ; changer le hash du nom de fichier pour invalider (logo.[hash].svg). Config : middleware dans frontend/nuxt.config.js.
# Themes
For each platform, there is a theme located in the folder common/$PLATFORM_NAME/theme.
This is were colors, fonts, breakpoints, etc. are defined. Import the file common/getTheme.js to dynamically get an object with all the variables defined:
import getTheme from "common/getTheme";
const theme = getTheme(process.env.PLATFORM_NAME);
console.log(theme);
/*
output:
{
borderRadius: {},
breakpoints: {},
colors: {},
fonts: {},
transitions: {}
}
*/
TIP
This object is injected in the nuxt application: this.$theme
# Element UI theme for the frontend
In order to deeply stick to the platform's identity, a custom theme for Element UI is generated. This theme written in sass extends the default theme from Element UI (theme-chalk (opens new window)).
The entry point of the theme is located in frontend/assets/styles/element-ui/index.scss.
Element UI has a set of overridable variables. The list of these variables is in this file (opens new window).
Our custom variables are located in frontend/assets/styles/element-ui/custom/variables.scss. As the original theme, variables are prefixed by --.
We use a generated css file per platform so whenever the theme changes, we need to regenerate them:
cd frontend
npm run element:themes
This command uses gulp to generate a css file for each platform in the folder element-ui. The task in the gulpfile uses a custom json loader to use json files as sass variables, allowing us to fetch the right theme for the right platform. As result of the task, each css file is named after its platform name. The css file corresponding to the current platform is then dynamically imported in the nuxt.config.js.
TIP
The theme doesn't change very ofter so in order to save some time at the build time, we chose to generate the theme separately using Gulp.
# Objects
In addition to the original theme, css objects have been created. Objects are reusable and abstract set of styles defined using sass placeholders (opens new window).
All objects are prefixed by -o- in order to be clearly identifiable.
Objects are located at frontend/assets/styles/element-ui/custom/objects/.
WARNING
Sass placeholders are not rendered in css. We use placeholders because we don't want to render the object styles every time we import a placeholder file. That would be very inconvenient!
If you want to use an object outside of scss, in the html for example, you can create the class selector that extends the placeholder in the file ~/assets/styles/element-ui/custom/objects/index.scss:
@import "./{PATH_TO_OBJECT}";
.-o-my-object {
@extends -o-my-object;
}
# Adding an object
Let's assume we want to add the layout object container.
Add the placeholder in a file ~/assets/styles/element-ui/custom/objects/layout.scss
%-o-container {
padding-left: 2rem;
padding-right: 2rem;
}
# Using an object
@import "./{PATH_TO_OBJECT}";
.my-selector {
@extend %-o-title-2;
}
# Mixins
# Breakpoints
The res-spec mixin have been created for media queries:
.my-selector {
// This style will be only applied to xs devices
@include res-spec(xs-only) {
padding-right: 50px;
}
}
TIP
You can see the list of keys here (opens new window)
⚠️ Breakpoints are defined in the theme of the platform.
# Components
Element UI components are written usig the BEM syntax (opens new window). They use mixins b, e, m, respectively Bloc, Element and Modifier to write their style. We chose to follow the same rules.
# Overriding a component style
To override the component el-button:
- Create a file named
buttonin the folder~/assets/styles/element-ui/custom/components/. - Add this comment a the top of the file:
// Custom style for Button // src: https://github.com/ElementUI/theme-chalk/blob/master/src/button.scss - Import files you need, for instance variables and mixins
- Add the custom style by following the same structure of the original file:
@include b(button) { // will automatically prepend with the prefix `el-` // custom style }
TIP
Before overriding a component, make sure the customization can't be achieved by just editing variables!
# Using theme's variables in stylus
It's possible to import JSON files as variables in stylus. A variable $platform-theme that represents the path to the current platform's theme is injected in the stylus loader so to import a JSON file, simply do:
json($platform-theme + '/colors.json')