Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
49216ed
starting place
jsundai Oct 24, 2025
b383f72
first basic workflow python
jsundai Nov 4, 2025
47a3a4f
adding components and sdk box logos
jsundai Nov 6, 2025
eab2cb4
language tabs
jsundai Nov 13, 2025
249d92a
rename for multilanguage
jsundai Nov 13, 2025
8f112b7
text edits
jsundai Nov 13, 2025
435aff1
component clean up
jsundai Nov 13, 2025
f78d689
adding custom language order for language tabs
jsundai Nov 13, 2025
e592d93
title and description change
jsundai Nov 13, 2025
c684dea
getting started section
jsundai Nov 13, 2025
302eb07
adding in workflow and activity definition base
jsundai Nov 17, 2025
0fa1868
refining retry policy section and adding each sdk tab
jsundai Nov 17, 2025
0186c4b
add comments to retry policy code
jsundai Nov 17, 2025
15533aa
add base of worker step
jsundai Nov 17, 2025
e5606d2
task queue base by language
jsundai Nov 17, 2025
ab55d22
add execute the workflow base
jsundai Nov 17, 2025
06af7a1
adding langauge tabs for crash test
jsundai Nov 19, 2025
938882c
different layout for crash test and friendlier language
jsundai Nov 19, 2025
bddc1ce
experiment 2 base by sdk
jsundai Nov 19, 2025
713e220
restructured live bug fix section
jsundai Nov 19, 2025
a93783e
react component for terminal animation
jsundai Nov 19, 2025
50b9dec
updating intro draft for failure simulation
jsundai Nov 19, 2025
ecc3a22
update index with cards
jsundai Nov 20, 2025
8f42e89
remove redundant components, edit intro
jsundai Nov 24, 2025
5ed31fa
add set up steps for project install in each language
jsundai Nov 24, 2025
5360c55
failure simulation content editS
jsundai Nov 30, 2025
8fcad02
adding php snippets for money transfer
jsundai Dec 1, 2025
f0c55c4
adding more php
jsundai Dec 1, 2025
99cffe2
add language tabs on commands
jsundai Dec 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,101 changes: 2,101 additions & 0 deletions docs/build-your-first-basic-workflow/build-your-first-workflow.mdx

Large diffs are not rendered by default.

1,126 changes: 1,126 additions & 0 deletions docs/build-your-first-basic-workflow/failure-simulation.mdx

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions docs/build-your-first-basic-workflow/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
id: index
title: Build your First Basic Workflow
sidebar_label: Build your First Basic Workflow
description: Learn Temporal's core concepts by building and running a money transfer Workflow that demonstrates reliability, failure handling, and live debugging.
hide_table_of_contents: true
keywords:
- temporal
- workflow
- getting started
- tutorial
- money transfer
tags:
- Getting Started
- Tutorial
---

# Build your First Basic Workflow

Build a money transfer app that survives crashes and handles failures gracefully.

import QuickstartCards from "@site/src/components/QuickstartCards";

<QuickstartCards
items={[
{
href: "/build-your-first-basic-workflow/build-your-first-workflow",
title: "Part 1: Build your First Workflow",
description: "Build a money transfer app and learn core Temporal concepts."
},
{
href: "/build-your-first-basic-workflow/failure-simulation",
title: "Part 2: Failure Simulation",
description: "Test server failures and runtime debugging with durable execution."
}
]}
/>
87 changes: 58 additions & 29 deletions sidebars.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,40 @@
module.exports = {
documentation: [
"index",
"quickstarts",
{
type: "link",
label: "Courses and Tutorials",
href: "https://learn.temporal.io/",
type: "category",
label: "Getting Started",
collapsed: false,
items: [
{
type: "category",
label: "Quickstarts",
collapsed: false,
link: {
type: "doc",
id: "quickstarts",
},
items: [],
},
{
type: "category",
label: "Build your First Basic Workflow",
collapsed: true,
link: {
type: "doc",
id: "build-your-first-basic-workflow/index",
},
items: [
"build-your-first-basic-workflow/build-your-first-workflow",
"build-your-first-basic-workflow/failure-simulation",
],
},
{
type: "link",
label: "Courses and Tutorials",
href: "https://learn.temporal.io/",
},
],
},
{
type: "category",
Expand Down Expand Up @@ -598,7 +627,7 @@ module.exports = {
"references/server-options",
"references/web-ui-configuration",
"references/web-ui-environment-variables",

],
},
{
Expand All @@ -613,7 +642,7 @@ module.exports = {
"troubleshooting/blob-size-limit-error",
"troubleshooting/deadline-exceeded-error",
"troubleshooting/last-connection-error",
"troubleshooting/performance-bottlenecks"
"troubleshooting/performance-bottlenecks"
],
},
{
Expand Down Expand Up @@ -642,37 +671,37 @@ module.exports = {
"encyclopedia/temporal",
"encyclopedia/temporal-sdks",
{
type: "category",
label: "Workflows",
collapsed: true,
link: {
type: "doc",
id: "encyclopedia/workflow/workflow-overview",
},
items: [
"encyclopedia/workflow/workflow-definition",
{
type: "category",
label: "Workflows",
label: "Workflow Execution",
collapsed: true,
link: {
type: "doc",
id: "encyclopedia/workflow/workflow-overview",
id: "encyclopedia/workflow/workflow-execution/workflow-execution",
},
items: [
"encyclopedia/workflow/workflow-definition",
{
type: "category",
label: "Workflow Execution",
collapsed: true,
link: {
type: "doc",
id: "encyclopedia/workflow/workflow-execution/workflow-execution",
},
items: [
"encyclopedia/workflow/workflow-execution/workflowid-runid",
"encyclopedia/workflow/workflow-execution/event",
"encyclopedia/workflow/workflow-execution/continue-as-new",
"encyclopedia/workflow/workflow-execution/limits",
"encyclopedia/workflow/workflow-execution/timers-delays",
],
},
"encyclopedia/workflow/dynamic-handler",
"encyclopedia/workflow/workflow-schedule",
"encyclopedia/workflow/cron-job",
"encyclopedia/workflow/patching",
"encyclopedia/workflow/workflow-execution/workflowid-runid",
"encyclopedia/workflow/workflow-execution/event",
"encyclopedia/workflow/workflow-execution/continue-as-new",
"encyclopedia/workflow/workflow-execution/limits",
"encyclopedia/workflow/workflow-execution/timers-delays",
],
},
"encyclopedia/workflow/dynamic-handler",
"encyclopedia/workflow/workflow-schedule",
"encyclopedia/workflow/cron-job",
"encyclopedia/workflow/patching",
],
},
{
type: "category",
label: "Activities",
Expand Down
123 changes: 123 additions & 0 deletions src/components/AnimatedTerminal/AnimatedTerminal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React, { useState, useEffect, useRef } from 'react';
import styles from './AnimatedTerminal.module.css';

export const AnimatedTerminal = ({
lines = [],
delay = 1000,
typingSpeed = 50,
prompt = "$",
autoStart = true,
startOnVisible = false,
loop = false,
restartDelay = 2000
}) => {
const [displayedLines, setDisplayedLines] = useState([]);
const [currentLineIndex, setCurrentLineIndex] = useState(0);
const [isTyping, setIsTyping] = useState(false);
const [isRestarting, setIsRestarting] = useState(false);
const [shouldStart, setShouldStart] = useState(!startOnVisible);
const terminalRef = useRef(null);

// Intersection Observer for scroll-triggered start
useEffect(() => {
if (!startOnVisible || shouldStart) return;

const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setShouldStart(true);
}
});
},
{
threshold: 0.3, // Trigger when 30% of the component is visible
rootMargin: '0px 0px -100px 0px' // Start slightly before it's fully visible
}
);

if (terminalRef.current) {
observer.observe(terminalRef.current);
}

return () => {
observer.disconnect();
};
}, [startOnVisible, shouldStart]);

useEffect(() => {
if (!shouldStart || !autoStart || lines.length === 0) return;

const showNextLine = () => {
if (currentLineIndex < lines.length) {
setIsTyping(true);

// Simulate typing effect for current line
const currentLine = lines[currentLineIndex];
let charIndex = 0;
const typingInterval = setInterval(() => {
if (charIndex <= currentLine.length) {
setDisplayedLines(prev => {
const newLines = [...prev];
newLines[currentLineIndex] = currentLine.slice(0, charIndex);
return newLines;
});
charIndex++;
} else {
clearInterval(typingInterval);
setIsTyping(false);
setCurrentLineIndex(prev => prev + 1);
}
}, typingSpeed);

return () => clearInterval(typingInterval);
} else if (loop && currentLineIndex === lines.length) {
// Animation complete, restart if looping
setIsRestarting(true);
const restartTimer = setTimeout(() => {
setDisplayedLines([]);
setCurrentLineIndex(0);
setIsRestarting(false);
}, restartDelay);

return () => clearTimeout(restartTimer);
}
};

const timer = setTimeout(() => {
showNextLine();
}, currentLineIndex === 0 ? 0 : delay);

return () => clearTimeout(timer);
}, [currentLineIndex, lines, delay, typingSpeed, autoStart, loop, restartDelay, shouldStart]);

return (
<div ref={terminalRef} className={styles.terminal}>
<div className={styles.terminalHeader}>
<div className={styles.terminalButtons}>
<span className={styles.close}></span>
<span className={styles.minimize}></span>
<span className={styles.maximize}></span>
</div>
<div className={styles.terminalTitle}>Terminal</div>
</div>
<div className={styles.terminalBody}>
{displayedLines.map((line, index) => (
<div key={`${currentLineIndex}-${index}`} className={styles.terminalLine}>
<span className={styles.prompt}>{prompt}</span>
<span className={styles.command}>{line}</span>
{index === currentLineIndex - 1 && isTyping && (
<span className={styles.cursor}>|</span>
)}
</div>
))}
{(currentLineIndex < lines.length && !isTyping && !isRestarting) && (
<div className={styles.terminalLine}>
<span className={styles.prompt}>{prompt}</span>
<span className={styles.cursor}>|</span>
</div>
)}
</div>
</div>
);
};
112 changes: 112 additions & 0 deletions src/components/AnimatedTerminal/AnimatedTerminal.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
.terminal {
background: #1e1e1e;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
margin: 1.5rem 0;
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Consolas', 'Liberation Mono', monospace;
font-size: 14px;
overflow: hidden;
}

.terminalHeader {
background: #323232;
padding: 8px 16px;
display: flex;
align-items: center;
border-bottom: 1px solid #444;
}

.terminalButtons {
display: flex;
gap: 8px;
margin-right: 16px;
}

.terminalButtons span {
width: 12px;
height: 12px;
border-radius: 50%;
}

.close {
background: #ff5f57;
}

.minimize {
background: #ffbd2e;
}

.maximize {
background: #28ca42;
}

.terminalTitle {
color: #ccc;
font-size: 12px;
font-weight: 500;
}

.terminalBody {
padding: 16px;
min-height: 120px;
background: #1e1e1e;
color: #f8f8f2;
}

.terminalLine {
display: flex;
align-items: center;
margin: 4px 0;
line-height: 1.4;
}

.prompt {
color: #50fa7b;
margin-right: 8px;
user-select: none;
}

.command {
color: #f8f8f2;
white-space: pre-wrap;
}

.cursor {
color: #f8f8f2;
animation: blink 1s infinite;
margin-left: 2px;
}

@keyframes blink {

0%,
50% {
opacity: 1;
}

51%,
100% {
opacity: 0;
}
}

/* Different colors for different types of output */
.terminalLine:has(.command:contains("ERROR")) .command,
.terminalLine .command:contains("ERROR") {
color: #ff5555;
}

.terminalLine:has(.command:contains("Withdrawing")) .command,
.terminalLine .command:contains("Withdrawing") {
color: #8be9fd;
}

.terminalLine:has(.command:contains("Depositing")) .command,
.terminalLine .command:contains("Depositing") {
color: #ffb86c;
}

.terminalLine:has(.command:contains("Running")) .command,
.terminalLine .command:contains("Running") {
color: #50fa7b;
}
Loading