diff --git a/frontend/src/api/cubicweb.ts b/frontend/src/api/cubicweb.ts
index a6e73e34395ab574adb132f635b4926bf4556a20_ZnJvbnRlbmQvc3JjL2FwaS9jdWJpY3dlYi50cw==..be74d7006c4eeb3db67b1dafe3e1887a754e7657_ZnJvbnRlbmQvc3JjL2FwaS9jdWJpY3dlYi50cw== 100644
--- a/frontend/src/api/cubicweb.ts
+++ b/frontend/src/api/cubicweb.ts
@@ -176,6 +176,18 @@
   }
 }
 
+export function useApiRunRecipe() {
+  const client = useClient();
+  const insertImportProcess =
+    "INSERT ImportProcess X: X import_procedure %(import_procedure)s, X import_recipe %(import_recipe)s";
+  return (recipeEid: number, projectEid: number) => {
+    client.execute(insertImportProcess, {
+      import_procedure: projectEid,
+      import_recipe: recipeEid,
+    });
+  };
+}
+
 export function useApiCreateRecipe() {
   const client = useClient();
   const insertRql =
diff --git a/frontend/src/app/project/[eid]/page.tsx b/frontend/src/app/project/[eid]/page.tsx
index a6e73e34395ab574adb132f635b4926bf4556a20_ZnJvbnRlbmQvc3JjL2FwcC9wcm9qZWN0L1tlaWRdL3BhZ2UudHN4..be74d7006c4eeb3db67b1dafe3e1887a754e7657_ZnJvbnRlbmQvc3JjL2FwcC9wcm9qZWN0L1tlaWRdL3BhZ2UudHN4 100644
--- a/frontend/src/app/project/[eid]/page.tsx
+++ b/frontend/src/app/project/[eid]/page.tsx
@@ -20,7 +20,7 @@
 import AddIcon from "@mui/icons-material/Add";
 import { RecipeModal } from "@/components/RecipeModal";
 import { useGetProject } from "@/hooks/useGetProject";
-import { useApiDeleteRecipe } from "@/api/cubicweb";
+import { useApiDeleteRecipe, useApiRunRecipe } from "@/api/cubicweb";
 
 export default function Project({
   params: { eid },
@@ -33,7 +33,7 @@
   const [selectedRecipeEid, setSelectedRecipeEid] = useState<
     number | undefined
   >();
-  const [deleteModal, setDeleteModal] = useState<{
+  const [modal, setModal] = useState<{
     visible: boolean;
     text?: string;
     eid?: number;
@@ -37,6 +37,7 @@
     visible: boolean;
     text?: string;
     eid?: number;
+    type?: "delete" | "run";
   }>({ visible: false });
   const [recipeModalOpen, setRecipeModalOpen] = useState(false);
   const deleteRecipe = useApiDeleteRecipe();
@@ -40,6 +41,7 @@
   }>({ visible: false });
   const [recipeModalOpen, setRecipeModalOpen] = useState(false);
   const deleteRecipe = useApiDeleteRecipe();
+  const runRecipe = useApiRunRecipe();
 
   if (isNaN(parsedEid)) {
     return <ErrorScreen message={`Projet '${eid}' inconnu`} />;
@@ -102,7 +104,7 @@
               }}
               selected={selectedRecipeEid === d.eid}
               onDelete={() =>
-                setDeleteModal({
+                setModal({
                   visible: true,
                   text: `Voulez vous vraiment supprimer la recette '${d.name}' ?`,
                   eid: d.eid,
@@ -106,6 +108,15 @@
                   visible: true,
                   text: `Voulez vous vraiment supprimer la recette '${d.name}' ?`,
                   eid: d.eid,
+                  type: "delete",
+                })
+              }
+              onRun={() =>
+                setModal({
+                  visible: true,
+                  text: `Voulez vous vraiment lancer la recette '${d.name}' ?`,
+                  eid: d.eid,
+                  type: "run",
                 })
               }
             />
@@ -120,7 +131,7 @@
         />
       </Stack>
       <ConfirmModal
-        open={deleteModal.visible}
-        text={deleteModal?.text ?? ""}
-        onClose={() => setDeleteModal((prev) => ({ ...prev, visible: false }))}
+        open={modal.visible}
+        text={modal?.text ?? ""}
+        onClose={() => setModal((prev) => ({ ...prev, visible: false }))}
         onAccept={async () => {
@@ -126,11 +137,15 @@
         onAccept={async () => {
-          if (deleteModal.eid) {
-            await deleteRecipe(deleteModal.eid);
-            const recipeList = data.import_recipes;
-            recipeList?.splice(
-              recipeList?.findIndex((p) => p.eid === deleteModal.eid),
-              1,
-            );
+          if (modal.eid) {
+            if (modal.type === "delete") {
+              await deleteRecipe(modal.eid);
+              const recipeList = data.import_recipes;
+              recipeList?.splice(
+                recipeList?.findIndex((p) => p.eid === modal.eid),
+                1,
+              );
+            } else {
+              await runRecipe(modal.eid, parsedEid);
+            }
           }
         }}
       />
diff --git a/frontend/src/components/cards/RecipeCard.tsx b/frontend/src/components/cards/RecipeCard.tsx
index a6e73e34395ab574adb132f635b4926bf4556a20_ZnJvbnRlbmQvc3JjL2NvbXBvbmVudHMvY2FyZHMvUmVjaXBlQ2FyZC50c3g=..be74d7006c4eeb3db67b1dafe3e1887a754e7657_ZnJvbnRlbmQvc3JjL2NvbXBvbmVudHMvY2FyZHMvUmVjaXBlQ2FyZC50c3g= 100644
--- a/frontend/src/components/cards/RecipeCard.tsx
+++ b/frontend/src/components/cards/RecipeCard.tsx
@@ -1,5 +1,7 @@
 import {
   Box,
+  Button,
+  CardActions,
   CardContent,
   IconButton,
   Stack,
@@ -10,6 +12,7 @@
 import { BaseCard, preventPropagation } from "./BaseCard";
 import CheckIcon from "@mui/icons-material/Check";
 import CloseIcon from "@mui/icons-material/Close";
+import PlayArrowIcon from "@mui/icons-material/PlayArrow";
 
 interface RecipeCardProps {
   name: string;
@@ -19,6 +22,7 @@
   lastProcessSuccess?: boolean;
   selected: boolean;
   onOpen?: () => void;
+  onRun?: () => void;
   onDelete?: () => void;
 }
 
@@ -31,6 +35,7 @@
   selected,
   onOpen,
   onDelete,
+  onRun,
 }: RecipeCardProps) {
   const theme = useTheme();
   return (
@@ -40,18 +45,12 @@
         backgroundColor: selected ? theme.palette.action.selected : undefined,
       }}
     >
-      <CardContent>
-        <Stack direction={"row"}>
-          <Typography variant="h5" component={"p"} fontWeight={"bold"} flex={1}>
-            {name}
-          </Typography>
-          <Box>
-            <IconButton
-              onClick={(e) => {
-                preventPropagation(e);
-                if (onDelete) {
-                  onDelete();
-                }
-              }}
-              onMouseDown={preventPropagation}
+      <Box display={"flex"} flexDirection={"column"} height={"100%"}>
+        <CardContent style={{ flex: 1 }}>
+          <Stack direction={"row"}>
+            <Typography
+              variant="h5"
+              component={"p"}
+              fontWeight={"bold"}
+              flex={1}
             >
@@ -57,26 +56,55 @@
             >
-              <DeleteIcon />
-            </IconButton>
-          </Box>
-        </Stack>
-        {lastProcessDate && lastProcessSuccess !== undefined ? (
-          <>
-            <Typography variant="body2">Dernier process</Typography>
-            <Stack direction={"row"} spacing={1}>
-              <Typography variant="body1">
-                {lastProcessDate.toLocaleDateString()}
-              </Typography>
-              {lastProcessSuccess ? (
-                <CheckIcon color="success" />
-              ) : (
-                <CloseIcon color="error" />
-              )}
-            </Stack>
-          </>
-        ) : null}
-        <Typography variant="body2">Process type: {processType}</Typography>
-        <Typography variant="body2">Data Service: {dataserviceName}</Typography>
-      </CardContent>
+              {name}
+            </Typography>
+            <Box>
+              <IconButton
+                onClick={(e) => {
+                  preventPropagation(e);
+                  if (onDelete) {
+                    onDelete();
+                  }
+                }}
+                onMouseDown={preventPropagation}
+              >
+                <DeleteIcon />
+              </IconButton>
+            </Box>
+          </Stack>
+          {lastProcessDate && lastProcessSuccess !== undefined ? (
+            <>
+              <Typography variant="body2">Dernier process</Typography>
+              <Stack direction={"row"} spacing={1}>
+                <Typography variant="body1">
+                  {lastProcessDate.toLocaleDateString()}
+                </Typography>
+                {lastProcessSuccess ? (
+                  <CheckIcon color="success" />
+                ) : (
+                  <CloseIcon color="error" />
+                )}
+              </Stack>
+            </>
+          ) : null}
+          <Typography variant="body2">Process type: {processType}</Typography>
+          <Typography variant="body2">
+            Data Service: {dataserviceName}
+          </Typography>
+        </CardContent>
+        <CardActions style={{ justifyContent: "end" }}>
+          <Button
+            endIcon={<PlayArrowIcon />}
+            onClick={(e) => {
+              preventPropagation(e);
+              if (onRun) {
+                onRun();
+              }
+            }}
+            onMouseDown={preventPropagation}
+          >
+            Lancer
+          </Button>
+        </CardActions>
+      </Box>
     </BaseCard>
   );
 }