Fujimod
브라우저에서 카메라 펌웨어를 시험하고 Fujimod SD 부팅 파일을 만든다
CoHabitat는 입주자에게 구독 없이 공동 공간, 자동 공유, 온실, 게시판을 하나의 앱으로 제공합니다
Offrez à vos locataires espaces communs, auto-partage, serre et babillard dans une seule application, sans abonnement pour eux. Essayez la démo.
라이프스타일HTML · PLpgSQLGitHub @simonvelucia-afk온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Plateforme auto-partage et espace résidence
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Deux façons de déployer, à partir du même code :
deploy/README.md.Aucune URL ni clé n'est écrite dans index.html : tout ce qui change
d'un déploiement à l'autre vit dans config.js.
Chaque immeuble est une instance séparée : sa propre base, ses propres comptes, ses propres données. Rien n'est partagé entre immeubles — c'est ce qui permet d'en vendre un sans toucher aux autres.
Le seul fichier qui diffère d'un immeuble à l'autre est config.js.
Tout le reste du code est identique.
node deploy/scripts/new-building.mjs \
--id pointe-est --nom "Pointe-Est" \
--site https://cohabitat.pointe-est.com \
--supabase https://abcxyz.supabase.co \
--cle eyJhbGciOi... > config.js
Le script produit le config.js de l'immeuble et rappelle les cinq
étapes restantes : appliquer le schéma au nouveau projet Supabase,
régler les URL d'authentification, publier le dépôt, promouvoir le
premier administrateur, enregistrer l'immeuble à la centrale.
Un dépôt par immeuble, parce que GitHub Pages ne sert qu'un seul site par dépôt et qu'un domaine personnalisé y est attaché. La façon la moins pénible de tenir plusieurs dépôts à jour :
# une fois, dans le dépôt de l'immeuble
git remote add upstream https://github.com/simonvelucia-afk/CoHabitat.git
# à chaque mise à jour
git fetch upstream && git merge upstream/main
git checkout --ours config.js && git add config.js # garder sa config
Comme config.js est le seul fichier propre à l'immeuble, c'est le seul
conflit possible, et il se résout toujours de la même façon.
Si le nombre d'immeubles devient inconfortable, un hébergeur statique qui accepte plusieurs domaines par site (Cloudflare Pages, Netlify) permet de revenir à un seul dépôt,
config.jschoisissant l'instance d'aprèswindow.location.hostname. GitHub Pages ne le permet pas.
Pas de dépôt ni d'URL à créer : le même checkout sert tous les
immeubles, et deploy/scripts/render-config.mjs génère config.js à
partir du .env de la machine. Voir deploy/README.md.
schema.sql, puis les fichiers de
sql/ dans l'ordre de leur numéro (000_ en premier)Project URL (ex: https://abcxyz.supabase.co)anon public keyOuvrez config.js et renseignez :
supabaseUrl: 'https://VOTRE_PROJECT_ID.supabase.co',
supabaseAnonKey: 'VOTRE_ANON_KEY',
siteUrl: 'https://votre-domaine',
Le même fichier porte l'URL de la centrale Modulimo (central), la
Machine Lunch, l'analytique et l'emplacement des librairies tierces.
Mettre central.enabled à false rend l'instance entièrement autonome :
plus aucune requête ne sort, la finance reste locale et le contrôle de
licence est court-circuité.
Qui peut toucher à un solde (sql/040_soldes_securises.sql). Personne
directement : adjust_balance n'est appelable que depuis la base. Un
résident paie de son propre solde (solde_debiter) et n'est remboursé que
de ce qu'il a payé pour la même réservation (solde_rembourser) ; un
administrateur crédite (admin_crediter) ; un covoiturage se facture en
base, une seule fois (trajet_confirmer). Aucune fonction de solde ou de
rôle n'est appelable sans connexion. Test : sql/tests/soldes_test.sql.
Les prix se calculent en base (sql/041_prix_en_base.sql). La page ne
dit plus « débite X $ » mais « je réserve ceci » : espace_reserver,
serre_louer / serre_facturer, vehicule_reserver /
vehicule_retourner / vehicule_annuler. La base vérifie le créneau
(toutes réservations confondues), lit le tarif en vigueur, calcule,
vérifie le solde, débite et enregistre, en une transaction. Un résident ne
peut plus écrire lui-même un prix ni créer une réservation sans payer.
Test : sql/tests/prix_test.sql.
Où vit le solde des résidents. Dans la base de l'immeuble, par
défaut, même quand la centrale est branchée : la centrale sert alors aux
licences, aux contrats et au réseau entre immeubles,
pas au solde. Un seul réglage le change : finance_central_enabled =
true dans system_settings. Il s'applique à tout le solde à la fois —
espaces, serre, véhicules, covoiturage, transferts aux dépendants,
paiements enregistrés par l'admin, paie des emplois.
cohabitat)index.html à la racinehttps://votre-user.github.io/cohabitatDans Supabase → Authentication → URL Configuration:
https://votre-user.github.io/cohabitathttps://votre-user.github.io/cohabitatrole → principal_adminL'immeuble a du travail à confier — la serre, le poulailler, la sabloponie, le covoiturage, la Machine Lunch, l'entretien — et des résidents prêts à le faire. Migration : sql/036_emplois.sql (test : sql/tests/emplois_test.sql).
emploi_remuneration au grand livre) ou payée hors application (chèque, virement) avec trace. Une même heure ne peut pas être payée deux fois. Avec la finance centralisée, seul le paiement hors application est proposé, pour ne pas créer d'écart avec le solde de la centraleLa machine, ses zones, ses cases, ses menus et le solde des acheteurs vivent dans la base de l'immeuble (migration sql/037_lunch_immeuble.sql, test sql/tests/lunch_test.sql). La centrale n'est plus requise pour vendre.
lunch_acheter) : la case est verrouillée, le prix lu en base — jamais celui envoyé par le kiosque —, le solde vérifié et débité, la case vidée. Deux personnes ne peuvent pas acheter la même case ; une demande renvoyée après une coupure ne débite pas deux foislunch_rembourser) si le robot ne livre pas : une seule fois, et la case retrouve son contenusql/038_lunch_numero_serie.sql). Le numéro devient l'identifiant de la machine, à passer au kiosque (?machine=LM-…)LM-AAAA-NNNNN-C — année de fabrication, rang dans l'année, clé de contrôle ISO 7064 MOD 37,36. La clé repère les fautes de frappe (toute faute d'un caractère, 99,8 % des inversions de chiffres voisins) ; elle n'est pas secrète. Modulimo fabrique les numéros avec node deploy/scripts/numero-serie-lunch.mjs generer 2026 1 20sql/039_lunch_retirer.sql) : machine revendue, déménagée ou hors service. Sa fiche, ses zones et ses cases disparaissent, son numéro de série redevient libre ; l'historique des achats et le grand livre restent. Si des plats sont encore dans les cases, l'application le signale et demande confirmationlunch_purchase et lunch_get_balance, ouvertes sans connexion, perdent leurs droitsOrdre de mise en service : jouer 037 puis 038, publier CoHabitat et le kiosque (dépôt LunchMachine), puis ajouter chaque machine par son numéro de série (Paramètres → Machine Lunch).
L'ancien module « Auto-partage » devient Mobilité partagée — MaaS, Mobility as a Service : les véhicules du bâtiment, les vélomobiles et le covoiturage entre résidents sont réunis dans une seule offre, sous le même onglet.
price_per_minute) débitée à la réservation, puis les kilomètres déclarés au retour (price_per_km). Le créneau est retenu qu'il serve ou non, comme une salle commune ; les kilomètres, eux, ne sont connus qu'au retour. Ce partage n'est pas cosmétique : les frais d'exploitation d'un véhicule (énergie, entretien, pneus, amortissement) suivent les kilomètres bien plus que les heures, et facturer le temps seul ferait fondre la marge précisément sur les longs trajets C'est ce qui rend les vélomobiles du bâtiment réservables : on en prend un pour une heure, seul, sans annoncer où l'on va — ce que le covoiturage, qui suppose un chauffeur approuvé et des passagers, ne permettait pasvehicle_type : automobile, vélomobile, vélo, autre) et un drapeau is_reservable. Décoché, le véhicule reste dans la flotte mais n'est accessible que par un trajet publié. La liste est groupée par mode, avec une pastille de disponibilité (libre / occupé jusqu'à…)check_vehicle_availability() regarde les réservations et les trajets publiés, si bien qu'un vélomobile engagé sur un covoiturage n'apparaît pas libre sur ce créneau. Un trajet sans heure d'arrivée estimée réserve le véhicule deux heuresvehicle_busy_slots()), bornes seulement — jamais qui a réservékm_ecart) et signalé à l'administration, sans affecter sa facturation. Au retour, la saisie du compteur arrête le temps facturé : la durée court de la prise au retour, pas jusqu'à la fin du créneau, et la distance est la différence des deux relevés. Rendre tôt coûte moins cher et libère le véhiculeserre_frais_mensuel, débité via le solde virtuel)SERRE_CULTURES_UNIQUES)Sous-menu ⚡ Énergie et confort du Tableau de bord. Module optionnel module_energie, coupé par défaut : l'admin l'active dans les réglages quand l'immeuble publie ses mesures
État de l'immeuble : normal, panne Hydro (sur batterie, délestage), panne internet (mode local) ou exercice, avec son niveau vert / bleu / orange et un message. Les admins le publient depuis l'écran ; le compte appareil de l'immeuble peut aussi le faire
Mon eau chaude : la consommation du logement aujourd'hui, sur 7 et sur 30 jours, comparée à la moyenne de l'immeuble. Un résident ne voit jamais les compteurs d'un voisin (RLS) ; la moyenne vient de la fonction eau_chaude_moyenne(), qui ne renvoie que des agrégats et rien sous trois logements mesurés
Énergie de l'immeuble : production solaire du jour et part d'eau chaude couverte pour tous ; production instantanée, batterie, réseau et réservoir en plus pour les admins (et en démonstration)
Alertes (fuite, gel, panne) : le résident voit celles de son logement et de l'immeuble, l'admin toutes, avec le nombre de personnes prévenues, et peut les marquer résolues. À l'insertion, un déclencheur écrit une notification aux résidents du logement concerné, ou aux admins pour une alerte d'immeuble — la bonne personne, pas tout l'immeuble
L'application affiche, elle ne pilote rien : aucune table ne commande un équipement
Alimentation : les mesures arrivent par le compte appareil de l'immeuble (e-mail en @device.local, même convention que la serre), qui peut écrire dans les quatre tables mais pas les effacer. Le pont MQTT de l'immotique viendra avec le matériel ; d'ici là, n'importe quel script peut publier par l'API REST :
curl -X POST "$SUPABASE_URL/rest/v1/eau_chaude_compteurs" \
-H "apikey: $ANON_KEY" -H "Authorization: Bearer $JETON_APPAREIL" \
-H "Content-Type: application/json" -H "Prefer: resolution=merge-duplicates" \
-d '{"jour":"2026-10-17","unit":"B-204","litres":118}'
Le logement est désigné comme dans profiles.unit. Un compteur se republie sans doublon (UNIQUE (jour, unit))
Traduit en français, anglais, espagnol et chinois ; consultable en mode démo (données fictives, aucune écriture)
Migration : sql/035_energie.sql — test des règles d'accès : sql/tests/energie_test.sql
nouveau → à l'étude → planifié → en cours → livré / écarté, avec un mot de l'équipe visible par tout le monde sous l'idéelab_*), pas dans le navigateur : c'est la matière première des prochaines versionssql/030_lab.sqlsql/011_elevages.sqlL'interface est disponible en français, anglais, espagnol et chinois (sélecteur dans la barre de navigation). Les conditions d'utilisation sont traduites dans les quatre langues. Le module serre est entièrement traduit : libellés, stades, noms de cultures, unités, systèmes d'irrigation et fertilisants. Les valeurs stockées en base restent en français (serre_cultures.culture, rendement_unite…) — seul l'affichage est traduit, pour ne pas casser les données existantes ni les clés d'icônes.
trackFeature(catégorie, action, détails) écrit dans deux canaux : Google Analytics 4 (uniquement après consentement explicite, Loi 25) et la table usage_logs de Supabase, lisible par les seuls administrateurs. user_type (demo / resident), la langue et l'horodatage sont posés par la fonction elle-même — un appelant n'a à fournir que ce qui est propre à son événement.
Une catégorie = un module, en anglais snake_case ; l'action nomme ce qui vient de se passer. Le catalogue complet vit en commentaire au-dessus de trackFeature() dans index.html, et fait foi :
| Catégorie | Actions |
|---|---|
platform | resident_login, demo_login, language_select |
landing | landing_view, plan_hover, contact_click |
navigation | page_view |
shared_spaces | space_reserved |
shared_mobility | vehicle_reserved, vehicle_reservation_cancelled, trip_published, trip_cancelled, trip_seat_requested, trip_booking_cancelled, driver_offer_sent |
greenhouse | zone_rented, zone_released, harvest_logged, culture_saved |
lunch | kiosk_opened, queue_joined, queue_left |
bulletin_board | post_published, post_deleted |
tickets | ticket_created, ticket_message_sent, ticket_status_changed |
lab | rate_feature, submit_idea, vote_idea, unvote_idea, comment_idea, set_idea_status, idea_deleted, switch_tab |
network | network_space_booked |
federation | federated_space_booked |
La catégorie covoiturage a disparu au profit de shared_mobility : depuis que le module s'appelle Mobilité partagée, le covoiturage et la réservation de véhicule sont deux façons d'utiliser la même flotte et n'ont pas à se compter séparément. Les lignes déjà écrites dans usage_logs gardent l'ancien nom — c'est le prix d'un renommage, à retenir en lisant l'historique.
Deux choses ne sont volontairement pas mesurées, faute d'écran correspondant : l'annulation d'une réservation d'espace, qui n'existe pas côté locataire (le remboursement se fait depuis Modulimo Admin), et l'achat lunch, qui se déroule dans le kiosque — une autre application, avec son propre suivi. CoHabitat ne voit du lunch que l'ouverture du kiosque et la file d'attente.
cohabitat.modulimo.com sert aussi de vitrine : un visiteur qui ne s'est
jamais connecté sur l'appareil arrive sur la page de vente (fonctions,
captures, forfaits, prise de contact) plutôt que sur le formulaire de
connexion. C'est l'option vitrine.enabled de config.js ;
new-building.mjs et render-config.mjs la désactivent pour les
immeubles, dont les visiteurs sont des résidants.
| Adresse | Effet |
|---|---|
/ | Page de vente (visiteur), connexion (résidant déjà venu sur l'appareil) |
/#essai | Démo ouverte directement — lien public des pages de promotion |
/#demo | Démo pour une tablette de présentation (panneau des modules) |
/#connexion | Formulaire de connexion, même pour un nouveau visiteur |
La page présentée en détail, avec le formulaire de demande de
présentation, vit sur modulimo.com/cohabitat
(dépôt modulimo-home). Les demandes arrivent dans la table
leads_pointe_est de la centrale, source_page = /cohabitat/, et par
courriel à [email protected].
Les événements de la page de vente sont écrits dans usage_logs (module
landing), avec ou sans consentement à Google Analytics : ce sont des
compteurs anonymes, sans identifiant de visiteur.
| Action | Quand |
|---|---|
landing_view | Page de vente affichée (metadata.origin : accueil ou login) |
demo_click | Entrée en démo (metadata.place : hero, apercu, lien_essai) |
booking_click | Clic vers la réservation d'un créneau (agenda de rendez-vous Google) |
contact_click | Clic vers le formulaire de présentation |
email_click | Clic sur [email protected] |
plan_hover | Survol d'un forfait plus d'une seconde |
Entonnoir des 30 derniers jours, dans le SQL Editor de la base de l'instance :
select action,
metadata->>'place' as endroit,
count(*) as nombre
from usage_logs
where module = 'landing'
and created_at > now() - interval '30 days'
group by 1, 2
order by 1, 3 desc;
À rapprocher des demandes reçues :
-- base centrale
select date_trunc('week', created_at) as semaine, count(*)
from leads_pointe_est
where source_page like '%/cohabitat/%'
group by 1 order by 1 desc;
| Table | Description |
|---|---|
profiles | Utilisateurs (liés à auth.users) |
common_spaces | Espaces communs |
space_pricing | Tarification des espaces |
space_reservations | Réservations d'espaces |
vehicles | Véhicules |
vehicle_pricing | Tarification des véhicules |
vehicle_reservations | Réservation directe d'un véhicule, relevés de compteur à la prise et au retour |
vehicle_couts | Frais d'exploitation du parc, séparés en fixes et variables (admin) |
trips | Trajets publiés par chauffeurs |
trip_stops | Arrêts intermédiaires |
trip_bookings | Demandes passagers |
driver_dependent_seats | Personnes à charge chauffeur |
trip_cargo_usage | Utilisation cargo |
transactions | Toutes les transactions financières |
real_payments | Paiements réels enregistrés par admins |
reservation_requests | Log de toutes les actions |
notifications | Notifications utilisateurs |
system_settings | Paramètres configurables |
serre_zones | Zones de culture de la serre (fixes) |
serre_locations | Locations mensuelles d'une zone par un locataire |
serre_cultures | Cycles de culture par section (1-3) d'une zone |
serre_recoltes | Journal des cueillettes : une ligne par passage (cultures continues) |
serre_fertilisations | Applications de fertilisant par section |
serre_irrigation_config | Config d'irrigation par section (zone_id, section) |
vehicle_pickup() et vehicle_return() : le compteur vit sur vehicles, que les résidents lisent sans l'écrire, et la durée comme la distance ne doivent pas dépendre de l'horloge du navigateurvehicle_marge() rapproche revenus et frais sur une période et calcule les tarifs qui auraient tenu la marge visée, chaque nature rapportée à son assiette : les frais fixes aux minutes facturées, les variables aux kilomètres. Ce sont des moyennes de flotte — un véhicule tarifé sous la cible est porté par les autres, et l'écran le dit. Rien de tout cela n'est visible côté résident : il voit ce que son tarif couvre, jamais la marge ni la politique de prixsql/031_mobilite_partagee.sql, sql/032_mobilite_km.sql, sql/033_mobilite_compteur.sql, sql/034_mobilite_couts.sqlvehicle_reservation et vehicle_reservation_refund à la liste blanche de types de finance-bridge (elle vit dans le projet central, hors de ce dépôt). Sans cela le débit est refusé et la réservation s'annule d'elle-même. Une instance autonome n'est pas concernée : elle passe par adjust_balance(), que la migration suffit à débloquer100svhrequestFullscreen()serre-iot/) ; la saisie manuelle vit uniquement dans le panneau admin (onglet 🌱 Serre) — sur la page Espaces, le bloc est en lecture seule pour tout le monde (même composant ConditionsSerre, prop readOnly), et la restriction est appliquée au niveau de la table par la RLS serre_lectures_insert, pas seulement masquée dans l'UImodule_serre)sql/009_serre.sql, sql/010_serre_reservoir_temps.sql, sql/012_serre_couts_module.sql, sql/013_serre_frais_base.sql, sql/014_serre_lectures_admin_insert.sql, sql/015_serre_plan_locataire.sql, sql/016_serre_recoltes_stades.sqlserre_reservoirs | Réservoirs d'eau de la serre |
serre_lectures | Lectures de capteurs (températures, niveaux) |
elevage_historique | Historique poulailler / sablonponie (événements) |
elevage_couts | Coûts d'exploitation serre / poulailler / sablonponie |
immeuble_etat | Énergie et confort : état de l'immeuble (mode + niveau), la ligne la plus récente fait foi |
energie_lectures | Énergie et confort : mesures de l'immeuble (solaire, batterie, réseau, réservoir) |
eau_chaude_compteurs | Énergie et confort : eau chaude par logement et par jour (lisible par son logement et les admins) |
immeuble_alertes | Énergie et confort : fuite, gel, panne — d'un logement ou de l'immeuble |
lab_evaluations | LAB : note 1-5 + commentaire d'un résident sur une fonction |
lab_idees | LAB : améliorations et nouvelles fonctions proposées |
lab_idee_votes | LAB : appuis à une idée (un par personne) |
lab_idee_commentaires | LAB : fil de discussion sous une idée |