Skip to main content

Vue d’ensemble

Kit’Asso utilise 13 tables PostgreSQL hébergées sur Nhost et exposées via Hasura GraphQL. La base de données est organisée en 4 domaines fonctionnels : le catalogue d’outils, les workflows guidés, les packs curés et le système de quiz avec scoring pondéré V2. Architecture :
  • Core Tables (5) : tools, categories, filters, tool_features, site_assets
  • Workflow Tables (2) : workflows, workflow_steps
  • Pack System (2) : tool_packs, pack_tools
  • Quiz System (5) : quizzes, quiz_questions, quiz_answers, quiz_recommendations, quiz_responses
Accès aux données :
  • GraphQL via Hasura (auto-généré depuis le schéma PostgreSQL)
  • Permissions Hasura par rôle (public/admin) — pas de RLS PostgreSQL
  • API Layer centralisée dans src/api/ avec apiCall() / apiCallVoid()

Core Tables

1. tools

Table principale du catalogue d’outils numériques. Colonnes :
CREATE TABLE tools (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  name TEXT UNIQUE NOT NULL,
  description TEXT NOT NULL,
  pricing_tier TEXT CHECK (pricing_tier IN ('Gratuit', 'Freemium', 'Payant', 'Entreprise')),
  category_id UUID REFERENCES categories(id) ON DELETE SET NULL,
  logo_url TEXT,
  website_url TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
Type TypeScript :
interface Tool {
  id: string;
  name: string;
  description: string;
  pricing_tier: 'Gratuit' | 'Freemium' | 'Payant' | 'Entreprise';
  category_id: string | null;
  logo_url: string | null;
  website_url: string | null;
  created_at: string;
}
Query GraphQL :
query {
  tools(order_by: { name: asc }) {
    id name description pricing_tier
    category_id logo_url website_url
  }
}

2. categories

Classification des outils par domaine d’activité.
CREATE TABLE categories (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  name TEXT UNIQUE NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
Exemples : Communication, Gestion de projet, Comptabilité, Marketing, Événementiel, Formation

3. filters

Définitions de fonctionnalités et capacités des outils.
CREATE TABLE filters (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  filter_type TEXT NOT NULL,
  value TEXT NOT NULL,
  feature_type TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

4. tool_features (Join Table)

Relation many-to-many entre tools et filters.
CREATE TABLE tool_features (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tool_id UUID REFERENCES tools(id) ON DELETE CASCADE NOT NULL,
  filter_id UUID REFERENCES filters(id) ON DELETE CASCADE NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(tool_id, filter_id)
);

5. site_assets

Gestion centralisée des assets du site (logos, images).
CREATE TABLE site_assets (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  name TEXT UNIQUE NOT NULL,
  url TEXT NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
Note : Les URLs pointent vers Nhost Storage (https://{subdomain}.storage.{region}.nhost.run/v1/files/{fileId}).

Workflow Tables

6. workflows

Parcours guidés étape par étape pour la transformation numérique.
CREATE TABLE workflows (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  title TEXT NOT NULL,
  description TEXT NOT NULL,
  difficulty TEXT CHECK (difficulty IN ('débutant', 'intermédiaire', 'expert')),
  duration TEXT NOT NULL,
  category TEXT NOT NULL,
  icon TEXT NOT NULL,
  status TEXT CHECK (status IN ('active', 'draft')) DEFAULT 'draft',
  steps JSONB NOT NULL DEFAULT '[]',
  display_order INTEGER DEFAULT 0,
  objective TEXT,
  completion_message TEXT,
  next_steps JSONB DEFAULT '[]',
  resources JSONB DEFAULT '[]',
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);
Query GraphQL (public — uniquement actifs) :
query {
  workflows(
    where: { status: { _eq: "active" } }
    order_by: { display_order: asc }
  ) {
    id title description difficulty duration category icon status
    steps display_order
  }
}

7. workflow_steps

Détails enrichis des étapes de workflow.
CREATE TABLE workflow_steps (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  workflow_id UUID REFERENCES workflows(id) ON DELETE CASCADE NOT NULL,
  step_number INTEGER NOT NULL,
  tool_name TEXT NOT NULL,
  action TEXT NOT NULL,
  tool_url TEXT,
  detailed_instructions JSONB DEFAULT '[]',
  practical_tip TEXT,
  completion_checklist TEXT[],
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

Pack System

8. tool_packs

Collections curées d’outils pour des cas d’usage spécifiques.
CREATE TABLE tool_packs (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  title TEXT NOT NULL,
  description TEXT NOT NULL,
  difficulty TEXT CHECK (difficulty IN ('débutant', 'intermédiaire', 'expert')),
  icon TEXT DEFAULT 'Package',
  color TEXT DEFAULT 'blue',
  display_order INTEGER DEFAULT 0,
  status TEXT CHECK (status IN ('active', 'draft')) DEFAULT 'active',
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

9. pack_tools (Join Table)

Relation many-to-many entre packs et tools avec ordering.
CREATE TABLE pack_tools (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  pack_id UUID REFERENCES tool_packs(id) ON DELETE CASCADE NOT NULL,
  tool_id UUID REFERENCES tools(id) ON DELETE CASCADE NOT NULL,
  display_order INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(pack_id, tool_id)
);

Quiz System

10. quizzes

CREATE TABLE quizzes (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  title TEXT NOT NULL,
  description TEXT,
  slug TEXT UNIQUE NOT NULL,
  is_active BOOLEAN DEFAULT TRUE,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

quiz_questions

Questions du quiz avec support de branchement conditionnel.
CREATE TABLE quiz_questions (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  quiz_id UUID REFERENCES quizzes(id) ON DELETE CASCADE NOT NULL,
  question_text TEXT NOT NULL,
  question_type TEXT CHECK (question_type IN ('single', 'multiple', 'scale')),
  order_index INTEGER NOT NULL,
  is_required BOOLEAN DEFAULT TRUE,
  help_text TEXT,
  next_question_rules JSONB,  -- V2 : règles de branchement conditionnel
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);
Branchement conditionnel (next_question_rules) :
[
  { "if_answer_value": "aucun", "go_to_question_id": "uuid-question-3" },
  { "if_answer_value": "avance", "go_to_question_id": "uuid-question-5" }
]

quiz_answers

Options de réponse avec scoring pondéré V2.
CREATE TABLE quiz_answers (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  question_id UUID REFERENCES quiz_questions(id) ON DELETE CASCADE NOT NULL,
  answer_text TEXT NOT NULL,
  answer_value TEXT NOT NULL,
  order_index INTEGER DEFAULT 0,
  scoring_weights JSONB,  -- V2 : pondération pour le scoring
  created_at TIMESTAMPTZ DEFAULT NOW()
);
Scoring weights (scoring_weights) :
{
  "tool:uuid-mailchimp": 5,
  "category:communication": 2,
  "pricing:gratuit": 1
}
Les clés supportées sont tool:<id>, category:<name>, et pricing:<tier>.

quiz_recommendations

Règles de recommandation (système legacy V1, remplacé par le scoring V2).
CREATE TABLE quiz_recommendations (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  quiz_id UUID REFERENCES quizzes(id) ON DELETE CASCADE NOT NULL,
  condition_logic JSONB NOT NULL,
  recommended_pack_ids UUID[],
  recommended_tool_ids UUID[],
  recommendation_text TEXT,
  priority INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

quiz_responses

Soumissions utilisateurs avec analytics.
CREATE TABLE quiz_responses (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  quiz_id UUID REFERENCES quizzes(id) ON DELETE CASCADE NOT NULL,
  answers JSONB NOT NULL,
  recommended_pack_ids UUID[],
  recommended_tool_ids UUID[],
  email TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
Query GraphQL pour charger un quiz (V2) :
query GetQuiz($slug: String!) {
  quizzes(where: { slug: { _eq: $slug }, is_active: { _eq: true } }) {
    id title description slug
    quiz_questions(order_by: { order_index: asc }) {
      id question_text question_type order_index is_required help_text
      next_question_rules
      quiz_answers(order_by: { order_index: asc }) {
        id answer_text answer_value scoring_weights
      }
    }
  }
}

Relations et Cardinalités

categories (1) ──< (N) tools
tools (N) ──< (N) filters (via tool_features)
tools (N) ──< (N) tool_packs (via pack_tools)
workflows (1) ──< (N) workflow_steps
quizzes (1) ──< (N) quiz_questions
quiz_questions (1) ──< (N) quiz_answers
quizzes (1) ──< (N) quiz_recommendations
quizzes (1) ──< (N) quiz_responses
Cascades :
  • Suppression d’un tool → supprime ses tool_features et pack_tools
  • Suppression d’un workflow → supprime ses workflow_steps
  • Suppression d’un quiz → supprime questions, answers, recommendations, responses
  • Suppression d’une category → SET NULL sur tools.category_id

Ressources

Permissions Hasura

Contrôle d’accès par rôle

Storage

Gestion des logos et assets via Nhost Storage

API Layer

Utilisation de l’API pour requêter via GraphQL

Nhost & GraphQL

Architecture backend