sagadeck 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +305 -0
- package/SKILL.md +148 -0
- package/bin/sagadeck.js +511 -0
- package/docs/ANDAMENTO.md +1255 -0
- package/docs/EXPERIENCIAS.md +39 -0
- package/docs/PLANO-EXPERIENCIAS.md +39 -0
- package/docs/PLANO-TESTE-AULAS-TECNICAS.md +44 -0
- package/docs/PLANO-TESTE-DESINFORMACAO.md +38 -0
- package/docs/REFERENCIA.md +1131 -0
- package/package.json +59 -0
- package/src/adaptive-layouts.js +18 -0
- package/src/ai/art-direction.js +8 -0
- package/src/ai/commands.js +130 -0
- package/src/ai/context.js +245 -0
- package/src/ai/deck-ai.js +1135 -0
- package/src/ai/directions.js +74 -0
- package/src/ai/document-materials.js +49 -0
- package/src/ai/document-visuals.js +215 -0
- package/src/ai/evaluation.js +31 -0
- package/src/ai/ground.js +55 -0
- package/src/ai/llm.js +292 -0
- package/src/ai/quality.js +51 -0
- package/src/ai/relay.js +45 -0
- package/src/ai/staged-generation.js +24 -0
- package/src/ai/transform.js +858 -0
- package/src/ai/usage.js +17 -0
- package/src/ai/variety.js +80 -0
- package/src/ai/video-frames.js +24 -0
- package/src/ai/video-generation.js +126 -0
- package/src/ai/web-operation.js +31 -0
- package/src/algo-catalog.js +153 -0
- package/src/algo-trace.js +139 -0
- package/src/api-client.js +514 -0
- package/src/api-collections.js +14 -0
- package/src/api-demo.js +222 -0
- package/src/aspect.js +40 -0
- package/src/build.js +323 -0
- package/src/carousel.js +56 -0
- package/src/chrome.js +65 -0
- package/src/code-highlight.js +68 -0
- package/src/code-lab-browser.js +22 -0
- package/src/code-lab.js +3 -0
- package/src/code-language.js +52 -0
- package/src/csv.js +74 -0
- package/src/decision-lab.js +20 -0
- package/src/deck-file.js +119 -0
- package/src/diagram/napkin-examples.js +13 -0
- package/src/diagram/napkin.js +539 -0
- package/src/docx.js +128 -0
- package/src/dynamics/git-sim.js +200 -0
- package/src/dynamics/layouts.js +112 -0
- package/src/elements.js +554 -0
- package/src/experiences.js +124 -0
- package/src/exploration.js +31 -0
- package/src/export/browser.js +53 -0
- package/src/export/estudo.js +67 -0
- package/src/export/pptx.js +475 -0
- package/src/export/roteiro.js +40 -0
- package/src/export/shots.js +182 -0
- package/src/figures/charts.js +383 -0
- package/src/figures/diagrams.js +117 -0
- package/src/figures/icons.js +166 -0
- package/src/figures/material-pictos.js +20 -0
- package/src/figures/pictos.js +255 -0
- package/src/figures/points.js +106 -0
- package/src/figures/qr.js +29 -0
- package/src/figures/ufmap.js +48 -0
- package/src/fiscal/autofix.js +377 -0
- package/src/fiscal/normalize.js +115 -0
- package/src/graph-lab.js +24 -0
- package/src/hologram.js +30 -0
- package/src/identity.js +86 -0
- package/src/import/crop.js +59 -0
- package/src/import/index.js +132 -0
- package/src/import/legacy-word.js +42 -0
- package/src/import/merge.js +45 -0
- package/src/import/office.js +123 -0
- package/src/import/omml.js +69 -0
- package/src/import/pdf-render.js +56 -0
- package/src/import/pptx.js +701 -0
- package/src/import/xml.js +42 -0
- package/src/infographic.js +401 -0
- package/src/layouts.js +723 -0
- package/src/lessons.js +171 -0
- package/src/library.js +399 -0
- package/src/markup.js +116 -0
- package/src/master.js +214 -0
- package/src/mcp/server.js +371 -0
- package/src/meeting.js +42 -0
- package/src/motion.js +56 -0
- package/src/package.js +116 -0
- package/src/playground.js +19 -0
- package/src/portal-scene.js +20 -0
- package/src/preferences.js +61 -0
- package/src/protect.js +51 -0
- package/src/purpose.js +24 -0
- package/src/pytrace.js +1092 -0
- package/src/research/duckduckgo.js +73 -0
- package/src/research/research.js +202 -0
- package/src/research/svg-image.js +17 -0
- package/src/research/visuals.js +52 -0
- package/src/runtime/api-collection-ui.js +5 -0
- package/src/runtime/api-collections.js +28 -0
- package/src/runtime/api-core.js +530 -0
- package/src/runtime/api-ui.js +966 -0
- package/src/runtime/base.css +1774 -0
- package/src/runtime/calc.js +139 -0
- package/src/runtime/code-lab.js +371 -0
- package/src/runtime/decision-lab.js +49 -0
- package/src/runtime/diagram.js +341 -0
- package/src/runtime/fit.js +268 -0
- package/src/runtime/fonts/caveat.css +2 -0
- package/src/runtime/fonts/comic-neue.css +3 -0
- package/src/runtime/fonts/fredoka.css +2 -0
- package/src/runtime/fonts/index.json +10 -0
- package/src/runtime/fonts/inter.css +2 -0
- package/src/runtime/fonts/patrick-hand.css +2 -0
- package/src/runtime/fonts/plus-jakarta-sans.css +2 -0
- package/src/runtime/fonts/press-start-2p.css +2 -0
- package/src/runtime/fonts/vt323.css +2 -0
- package/src/runtime/formula.js +148 -0
- package/src/runtime/graph-lab.js +72 -0
- package/src/runtime/meeting.css +7 -0
- package/src/runtime/meeting.js +10 -0
- package/src/runtime/motion.js +15 -0
- package/src/runtime/playground.js +11 -0
- package/src/runtime/points.js +19 -0
- package/src/runtime/portal-scene.css +6 -0
- package/src/runtime/portal-scene.js +22 -0
- package/src/runtime/runtime.js +827 -0
- package/src/runtime/science.js +89 -0
- package/src/runtime/skins/aluminio.css +31 -0
- package/src/runtime/skins/arcade.css +25 -0
- package/src/runtime/skins/aurora.css +17 -0
- package/src/runtime/skins/bauhaus.css +19 -0
- package/src/runtime/skins/editorial.css +19 -0
- package/src/runtime/skins/jornal.css +17 -0
- package/src/runtime/skins/manual-noite.css +14 -0
- package/src/runtime/skins/manual.css +14 -0
- package/src/runtime/skins/noite.css +21 -0
- package/src/runtime/skins/oceano.css +17 -0
- package/src/runtime/skins/pop.css +23 -0
- package/src/runtime/skins/prata.css +18 -0
- package/src/runtime/skins/prisma.css +28 -0
- package/src/runtime/skins/rabisco.css +18 -0
- package/src/runtime/skins/relevo.css +33 -0
- package/src/runtime/skins/sinal.css +16 -0
- package/src/runtime/skins/terminal.css +23 -0
- package/src/runtime/vendor/KATEX-LICENSE.txt +21 -0
- package/src/runtime/vendor/MERMAID-LICENSE.txt +21 -0
- package/src/runtime/vendor/PLOTLY-LICENSE.txt +21 -0
- package/src/runtime/vendor/katex.css +1 -0
- package/src/runtime/vendor/mermaid.min.js +3636 -0
- package/src/runtime/vendor/plotly.min.js +3620 -0
- package/src/runtime/video-player.js +35 -0
- package/src/science.js +162 -0
- package/src/studio/ai-response.js +36 -0
- package/src/studio/api-routes.js +152 -0
- package/src/studio/assets/contexto/leia-me.md +12 -0
- package/src/studio/assets/contexto/vendas.csv +7 -0
- package/src/studio/assets/imagens/colecao-arquitetura.png +0 -0
- package/src/studio/assets/imagens/colecao-cor.png +0 -0
- package/src/studio/assets/imagens/colecao-equipe.png +0 -0
- package/src/studio/assets/imagens/lavanda-cover.jpg +0 -0
- package/src/studio/code-routes.js +32 -0
- package/src/studio/command-approval.js +48 -0
- package/src/studio/demo-decks.js +98 -0
- package/src/studio/direction-routes.js +29 -0
- package/src/studio/errors.js +65 -0
- package/src/studio/exploration-demo.js +17 -0
- package/src/studio/exporting.js +105 -0
- package/src/studio/generation-report.js +10 -0
- package/src/studio/instance.js +48 -0
- package/src/studio/layout-samples.js +152 -0
- package/src/studio/project.js +371 -0
- package/src/studio/public/api-collections.js +28 -0
- package/src/studio/public/app.js +5265 -0
- package/src/studio/public/art-preview.js +10 -0
- package/src/studio/public/calc-fields.js +11 -0
- package/src/studio/public/chat-progress.js +47 -0
- package/src/studio/public/developer-fields.js +22 -0
- package/src/studio/public/explorer.js +443 -0
- package/src/studio/public/history.js +58 -0
- package/src/studio/public/index.html +867 -0
- package/src/studio/public/inspector.js +270 -0
- package/src/studio/public/lab-fields.js +5 -0
- package/src/studio/public/library.css +275 -0
- package/src/studio/public/library.html +55 -0
- package/src/studio/public/library.js +471 -0
- package/src/studio/public/merge-decks.js +155 -0
- package/src/studio/public/review-ui.js +100 -0
- package/src/studio/public/screenshot-editor.js +140 -0
- package/src/studio/public/share-ui.js +72 -0
- package/src/studio/public/slide-clipboard.js +23 -0
- package/src/studio/public/slide-form.js +1263 -0
- package/src/studio/public/studio-awareness.js +154 -0
- package/src/studio/public/studio-next.css +303 -0
- package/src/studio/public/style.css +1262 -0
- package/src/studio/public/ui-icons.js +2 -0
- package/src/studio/public/viewers.js +372 -0
- package/src/studio/public/visual-editor.js +326 -0
- package/src/studio/public/workspace.js +18 -0
- package/src/studio/public-files.js +1 -0
- package/src/studio/request-helpers.js +41 -0
- package/src/studio/server.js +1583 -0
- package/src/studio/share-routes.js +146 -0
- package/src/studio/slide-copy-routes.js +26 -0
- package/src/studio/slide-copy.js +30 -0
- package/src/studio/snapshot.js +160 -0
- package/src/studio/style-routes.js +103 -0
- package/src/studio/template-collections.js +97 -0
- package/src/studio/versions.js +95 -0
- package/src/studio/video-download.js +29 -0
- package/src/studio/visual-keys.js +52 -0
- package/src/studio/workspaces.js +39 -0
- package/src/table.js +93 -0
- package/src/templates/scaffold.js +372 -0
- package/src/themes.js +604 -0
- package/src/trace-view.js +450 -0
- package/src/uid.js +19 -0
- package/src/video-player.js +40 -0
- package/src/visual-edits.js +99 -0
- package/src/ws.js +134 -0
- package/templates/cenario/Texto no cen/303/241rio.yaml" +171 -0
- package/templates/cenario/imagens/cidade.svg +30 -0
- package/templates/cenario/imagens/pessoa.svg +15 -0
- package/templates/cenario-e-ciencia.yaml +47 -0
- package/templates/ensaio-api.yaml +160 -0
- package/templates/exemplo-alegre.yaml +75 -0
- package/templates/exemplo-keynote.yaml +90 -0
- package/templates/exemplo-napkin.yaml +139 -0
- package/templates/exemplo.yaml +228 -0
package/src/ws.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// WebSocket mínimo (RFC 6455) sem dependências: cliente (Studio → serviço de conversa em tempo real) e o
|
|
2
|
+
// lado servidor (usado pela API de mentira). Feito à mão para aceitar cabeçalhos (token) e o certificado
|
|
3
|
+
// da empresa (ca), que o WebSocket do navegador/Node não deixam configurar.
|
|
4
|
+
import crypto from "node:crypto";
|
|
5
|
+
import net from "node:net";
|
|
6
|
+
import tls from "node:tls";
|
|
7
|
+
import { EventEmitter } from "node:events";
|
|
8
|
+
|
|
9
|
+
const GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
|
10
|
+
const accept = (key) => crypto.createHash("sha1").update(key + GUID).digest("base64");
|
|
11
|
+
|
|
12
|
+
// ---------- quadros ----------
|
|
13
|
+
function encode(data, { opcode, mask }) {
|
|
14
|
+
const payload = Buffer.isBuffer(data) ? data : Buffer.from(String(data), "utf8");
|
|
15
|
+
const op = opcode ?? (Buffer.isBuffer(data) ? 0x2 : 0x1);
|
|
16
|
+
const len = payload.length;
|
|
17
|
+
const head = [0x80 | op];
|
|
18
|
+
let ext = Buffer.alloc(0);
|
|
19
|
+
if (len < 126) head.push((mask ? 0x80 : 0) | len);
|
|
20
|
+
else if (len < 65536) { head.push((mask ? 0x80 : 0) | 126); ext = Buffer.alloc(2); ext.writeUInt16BE(len); }
|
|
21
|
+
else { head.push((mask ? 0x80 : 0) | 127); ext = Buffer.alloc(8); ext.writeBigUInt64BE(BigInt(len)); }
|
|
22
|
+
if (!mask) return Buffer.concat([Buffer.from(head), ext, payload]);
|
|
23
|
+
const key = crypto.randomBytes(4);
|
|
24
|
+
const masked = Buffer.alloc(len);
|
|
25
|
+
for (let i = 0; i < len; i++) masked[i] = payload[i] ^ key[i & 3];
|
|
26
|
+
return Buffer.concat([Buffer.from(head), ext, key, masked]);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Conexão já estabelecida (depois do handshake), dos dois lados.
|
|
30
|
+
class Conn extends EventEmitter {
|
|
31
|
+
constructor(socket, { client }) {
|
|
32
|
+
super();
|
|
33
|
+
this.socket = socket;
|
|
34
|
+
this.client = client; // cliente mascara o que envia
|
|
35
|
+
this.buf = Buffer.alloc(0);
|
|
36
|
+
this.parts = null; // mensagem fragmentada em andamento
|
|
37
|
+
this.open = true;
|
|
38
|
+
socket.on("data", (d) => { this.buf = Buffer.concat([this.buf, d]); this.parse(); });
|
|
39
|
+
socket.on("close", () => { if (this.open) { this.open = false; this.emit("close", 1006, "conexão caiu"); } });
|
|
40
|
+
// conexão derrubada do outro lado (ECONNRESET…): vira "close", nunca um erro solto que derruba o Studio
|
|
41
|
+
socket.on("error", (e) => {
|
|
42
|
+
if (this.listenerCount("error")) this.emit("error", e);
|
|
43
|
+
if (this.open) { this.open = false; this.emit("close", 1006, e.message); }
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
parse() {
|
|
47
|
+
for (;;) {
|
|
48
|
+
if (this.buf.length < 2) return;
|
|
49
|
+
const b0 = this.buf[0], b1 = this.buf[1];
|
|
50
|
+
const fin = !!(b0 & 0x80), op = b0 & 0x0f, masked = !!(b1 & 0x80);
|
|
51
|
+
let len = b1 & 0x7f, off = 2;
|
|
52
|
+
if (len === 126) { if (this.buf.length < 4) return; len = this.buf.readUInt16BE(2); off = 4; }
|
|
53
|
+
else if (len === 127) { if (this.buf.length < 10) return; len = Number(this.buf.readBigUInt64BE(2)); off = 10; }
|
|
54
|
+
const need = off + (masked ? 4 : 0) + len;
|
|
55
|
+
if (this.buf.length < need) return;
|
|
56
|
+
let payload = this.buf.subarray(off + (masked ? 4 : 0), need);
|
|
57
|
+
if (masked) { const k = this.buf.subarray(off, off + 4); payload = Buffer.from(payload.map((x, i) => x ^ k[i & 3])); }
|
|
58
|
+
this.buf = this.buf.subarray(need);
|
|
59
|
+
if (op === 0x8) { // close
|
|
60
|
+
const code = payload.length >= 2 ? payload.readUInt16BE(0) : 1005;
|
|
61
|
+
if (this.open) { this.open = false; try { this.socket.write(encode(payload.subarray(0, 2), { opcode: 0x8, mask: this.client })); } catch {} this.socket.end(); this.emit("close", code, payload.subarray(2).toString()); }
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (op === 0x9) { this.socket.write(encode(payload, { opcode: 0xa, mask: this.client })); continue; } // ping → pong
|
|
65
|
+
if (op === 0xa) continue;
|
|
66
|
+
if (op === 0x0) { if (!this.parts) continue; this.parts.chunks.push(payload); }
|
|
67
|
+
else this.parts = { op, chunks: [payload] };
|
|
68
|
+
if (fin && this.parts) {
|
|
69
|
+
const all = Buffer.concat(this.parts.chunks), isText = this.parts.op === 0x1;
|
|
70
|
+
this.parts = null;
|
|
71
|
+
this.emit("message", isText ? all.toString("utf8") : all, isText);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
send(data) { if (this.open) this.socket.write(encode(data, { mask: this.client })); }
|
|
76
|
+
close(code = 1000) {
|
|
77
|
+
if (!this.open) return;
|
|
78
|
+
const p = Buffer.alloc(2); p.writeUInt16BE(code);
|
|
79
|
+
try { this.socket.write(encode(p, { opcode: 0x8, mask: this.client })); } catch {}
|
|
80
|
+
this.open = false;
|
|
81
|
+
setTimeout(() => this.socket.destroy(), 200);
|
|
82
|
+
this.emit("close", code, "");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Cliente: ws:// ou wss://, com cabeçalhos e certificado da empresa.
|
|
87
|
+
export function connectWs(url, { headers = {}, ca, insecure = false, timeout = 15000, protocols } = {}) {
|
|
88
|
+
return new Promise((resolve, reject) => {
|
|
89
|
+
let u;
|
|
90
|
+
try { u = new URL(url); } catch { reject(Object.assign(new Error(`Endereço inválido: ${url}`), { kind: "config" })); return; }
|
|
91
|
+
if (!/^wss?:$/.test(u.protocol)) { reject(Object.assign(new Error(`Conversa em tempo real precisa de ws:// ou wss:// (veio ${u.protocol})`), { kind: "config" })); return; }
|
|
92
|
+
const secure = u.protocol === "wss:";
|
|
93
|
+
const port = Number(u.port) || (secure ? 443 : 80);
|
|
94
|
+
const key = crypto.randomBytes(16).toString("base64");
|
|
95
|
+
const opts = { host: u.hostname, port, servername: u.hostname, ca, rejectUnauthorized: !insecure };
|
|
96
|
+
const socket = secure ? tls.connect(opts) : net.connect(opts);
|
|
97
|
+
const timer = setTimeout(() => { socket.destroy(); reject(Object.assign(new Error(`sem resposta de ${u.host} em ${Math.round(timeout / 1000)}s`), { code: "TIMEOUT" })); }, timeout);
|
|
98
|
+
socket.once("error", (e) => { clearTimeout(timer); reject(e); });
|
|
99
|
+
socket.once(secure ? "secureConnect" : "connect", () => {
|
|
100
|
+
const lines = [`GET ${u.pathname}${u.search} HTTP/1.1`, `Host: ${u.host}`, "Upgrade: websocket", "Connection: Upgrade",
|
|
101
|
+
`Sec-WebSocket-Key: ${key}`, "Sec-WebSocket-Version: 13", ...(protocols ? [`Sec-WebSocket-Protocol: ${[].concat(protocols).join(", ")}`] : []),
|
|
102
|
+
...Object.entries(headers).map(([k, v]) => `${k}: ${v}`)];
|
|
103
|
+
socket.write(lines.join("\r\n") + "\r\n\r\n");
|
|
104
|
+
});
|
|
105
|
+
let head = Buffer.alloc(0);
|
|
106
|
+
const onData = (d) => {
|
|
107
|
+
head = Buffer.concat([head, d]);
|
|
108
|
+
const end = head.indexOf("\r\n\r\n");
|
|
109
|
+
if (end < 0) return;
|
|
110
|
+
socket.removeListener("data", onData);
|
|
111
|
+
clearTimeout(timer);
|
|
112
|
+
const text = head.subarray(0, end).toString();
|
|
113
|
+
const status = Number((text.match(/^HTTP\/1\.1 (\d+)/) || [])[1]);
|
|
114
|
+
if (status !== 101 || !text.toLowerCase().includes(`sec-websocket-accept: ${accept(key).toLowerCase()}`)) {
|
|
115
|
+
socket.destroy();
|
|
116
|
+
const body = head.subarray(end + 4).toString().slice(0, 400);
|
|
117
|
+
reject(Object.assign(new Error(`o serviço recusou a conexão (HTTP ${status || "?"})${body ? ": " + body : ""}`), { status }));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const conn = new Conn(socket, { client: true });
|
|
121
|
+
const rest = head.subarray(end + 4);
|
|
122
|
+
resolve(conn);
|
|
123
|
+
if (rest.length) { conn.buf = rest; conn.parse(); }
|
|
124
|
+
};
|
|
125
|
+
socket.on("data", onData);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Servidor: responde ao "upgrade" de um http.Server e devolve a conexão (usado pela API de mentira).
|
|
130
|
+
export function acceptWs(req, socket) {
|
|
131
|
+
const key = req.headers["sec-websocket-key"];
|
|
132
|
+
socket.write(["HTTP/1.1 101 Switching Protocols", "Upgrade: websocket", "Connection: Upgrade", `Sec-WebSocket-Accept: ${accept(key)}`].join("\r\n") + "\r\n\r\n");
|
|
133
|
+
return new Conn(socket, { client: false });
|
|
134
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Demonstração do "Texto no cenário" (layout scenography): todas as composições e tudo o que dá para ajustar.
|
|
2
|
+
# Biblioteca: Nova, "Exemplo: texto no cenário". As imagens de exemplo estão em imagens/ (troque pelas suas).
|
|
3
|
+
title: Texto no cenário
|
|
4
|
+
theme: aurora
|
|
5
|
+
motion: none
|
|
6
|
+
author: Seu nome
|
|
7
|
+
duration: 15
|
|
8
|
+
slides:
|
|
9
|
+
- layout: scenography
|
|
10
|
+
scene: stage
|
|
11
|
+
kicker: DEMONSTRAÇÃO
|
|
12
|
+
title: "TEXTO NO\nCENÁRIO"
|
|
13
|
+
subtitle: Treze composições e tudo o que dá para ajustar.
|
|
14
|
+
caption: SAGADECK / TEXTO NO CENÁRIO
|
|
15
|
+
notes: Cada slide deste deck mostra uma composição (campo scene) ou uma opção. Abra o painel Formatar para ver os campos.
|
|
16
|
+
|
|
17
|
+
- layout: section
|
|
18
|
+
title: As composições
|
|
19
|
+
subtitle: Campo "Composição" (scene). O texto continua editável em todas.
|
|
20
|
+
|
|
21
|
+
- layout: scenography
|
|
22
|
+
scene: stage
|
|
23
|
+
kicker: "scene: stage"
|
|
24
|
+
title: "ALÉM DO\nÓBVIO"
|
|
25
|
+
subtitle: Palco e profundidade. Letras monumentais atrás de uma escultura.
|
|
26
|
+
caption: PALCO E PROFUNDIDADE
|
|
27
|
+
|
|
28
|
+
- layout: scenography
|
|
29
|
+
scene: floor
|
|
30
|
+
kicker: "scene: floor"
|
|
31
|
+
title: "NOVOS\nCAMINHOS"
|
|
32
|
+
caption: CHÃO EM PERSPECTIVA
|
|
33
|
+
|
|
34
|
+
- layout: scenography
|
|
35
|
+
scene: signs
|
|
36
|
+
kicker: "scene: signs"
|
|
37
|
+
title: "IDEIAS\nEM CENA"
|
|
38
|
+
subtitle: Uma placa na cidade.
|
|
39
|
+
caption: PLACAS NA CIDADE
|
|
40
|
+
|
|
41
|
+
- layout: scenography
|
|
42
|
+
scene: terminal
|
|
43
|
+
kicker: ./acesso --scene terminal
|
|
44
|
+
title: "acesso\nconcedido"
|
|
45
|
+
subtitle: Segurança começa pela curiosidade.
|
|
46
|
+
caption: TERMINAL HACKER
|
|
47
|
+
|
|
48
|
+
- layout: scenography
|
|
49
|
+
scene: cafe
|
|
50
|
+
kicker: "Hoje no cardápio (scene: cafe)"
|
|
51
|
+
title: "Ideias coadas\nna hora"
|
|
52
|
+
subtitle: Com calma, açúcar a gosto.
|
|
53
|
+
caption: LOUSA DE CAFÉ
|
|
54
|
+
|
|
55
|
+
- layout: scenography
|
|
56
|
+
scene: travel
|
|
57
|
+
kicker: "EMBARQUE IMEDIATO / scene: travel"
|
|
58
|
+
title: "PRÓXIMO\nDESTINO"
|
|
59
|
+
subtitle: O plano para os próximos 12 meses.
|
|
60
|
+
caption: CARTÃO DE EMBARQUE
|
|
61
|
+
|
|
62
|
+
- layout: scenography
|
|
63
|
+
scene: ticker
|
|
64
|
+
kicker: "Q3 2026 / scene: ticker"
|
|
65
|
+
title: "RESULTADO\nRECORDE"
|
|
66
|
+
subtitle: Receita 38% acima do ano passado.
|
|
67
|
+
caption: PREGÃO FINANCEIRO
|
|
68
|
+
|
|
69
|
+
- layout: scenography
|
|
70
|
+
scene: marquee
|
|
71
|
+
kicker: "EM CARTAZ / scene: marquee"
|
|
72
|
+
title: "HOJE:\nA ESTREIA"
|
|
73
|
+
subtitle: Sessão única, entrada franca.
|
|
74
|
+
caption: LETREIRO DE CINEMA
|
|
75
|
+
|
|
76
|
+
- layout: scenography
|
|
77
|
+
scene: blueprint
|
|
78
|
+
kicker: "scene: blueprint"
|
|
79
|
+
title: "PROJETO\nDO FUTURO"
|
|
80
|
+
subtitle: medidas em ideias, escala 1:1
|
|
81
|
+
caption: PLANTA TÉCNICA
|
|
82
|
+
|
|
83
|
+
- layout: scenography
|
|
84
|
+
scene: magazine
|
|
85
|
+
kicker: "CAPA / scene: magazine"
|
|
86
|
+
title: "O ANO DA\nVIRADA"
|
|
87
|
+
subtitle: Como uma equipe pequena mudou o jogo.
|
|
88
|
+
caption: CAPA DE REVISTA
|
|
89
|
+
|
|
90
|
+
- layout: scenography
|
|
91
|
+
scene: orbit
|
|
92
|
+
kicker: "scene: orbit"
|
|
93
|
+
title: "MISSÃO\nCUMPRIDA"
|
|
94
|
+
subtitle: Da ideia à órbita em seis meses.
|
|
95
|
+
caption: ÓRBITA
|
|
96
|
+
|
|
97
|
+
- layout: scenography
|
|
98
|
+
scene: synthwave
|
|
99
|
+
kicker: "scene: synthwave"
|
|
100
|
+
title: "DE VOLTA\nAO FUTURO"
|
|
101
|
+
subtitle: As ideias que voltaram com tudo.
|
|
102
|
+
caption: NEON ANOS 80
|
|
103
|
+
|
|
104
|
+
- layout: scenography
|
|
105
|
+
scene: gallery
|
|
106
|
+
kicker: "scene: gallery"
|
|
107
|
+
title: "Menos\né mais"
|
|
108
|
+
subtitle: Uma ideia por parede.
|
|
109
|
+
caption: PAREDE DE GALERIA
|
|
110
|
+
|
|
111
|
+
- layout: section
|
|
112
|
+
title: E dá para ajustar
|
|
113
|
+
subtitle: Imagem de fundo, transparência, recorte na frente das letras e tamanho do texto.
|
|
114
|
+
|
|
115
|
+
- layout: scenography
|
|
116
|
+
scene: stage
|
|
117
|
+
image: imagens/cidade.svg
|
|
118
|
+
imageOpacity: 1
|
|
119
|
+
kicker: "image: imagens/cidade.svg"
|
|
120
|
+
title: "IMAGEM DE\nFUNDO"
|
|
121
|
+
subtitle: "Imagem de fundo (image), sem transparência: imageOpacity: 1"
|
|
122
|
+
caption: IMAGEM DE FUNDO
|
|
123
|
+
notes: Troque imagens/cidade.svg por uma foto sua (arquivo ao lado do deck ou link).
|
|
124
|
+
|
|
125
|
+
- layout: scenography
|
|
126
|
+
scene: stage
|
|
127
|
+
image: imagens/cidade.svg
|
|
128
|
+
imageOpacity: 0.3
|
|
129
|
+
kicker: "imageOpacity: 0.3"
|
|
130
|
+
title: "MAIS\nTRANSPARENTE"
|
|
131
|
+
subtitle: De 0 (some) a 1 (inteira). Sem o campo, fica em 0.85.
|
|
132
|
+
caption: TRANSPARÊNCIA DO FUNDO
|
|
133
|
+
|
|
134
|
+
- layout: scenography
|
|
135
|
+
scene: floor
|
|
136
|
+
foreground: imagens/pessoa.svg
|
|
137
|
+
kicker: "foreground: imagens/pessoa.svg"
|
|
138
|
+
title: "NA FRENTE\nDAS LETRAS"
|
|
139
|
+
caption: RECORTE EM PRIMEIRO PLANO
|
|
140
|
+
notes: O recorte (PNG ou SVG com fundo transparente, do tamanho do slide) fica por cima do texto. O fundo não é recortado sozinho; recorte a pessoa num editor.
|
|
141
|
+
|
|
142
|
+
- layout: scenography
|
|
143
|
+
scene: gallery
|
|
144
|
+
foreground: imagens/pessoa.svg
|
|
145
|
+
kicker: "foreground + gallery"
|
|
146
|
+
title: "Olhe de\nperto"
|
|
147
|
+
subtitle: Alguém parado diante da parede.
|
|
148
|
+
caption: RECORTE NA GALERIA
|
|
149
|
+
|
|
150
|
+
- layout: scenography
|
|
151
|
+
scene: stage
|
|
152
|
+
image: imagens/cidade.svg
|
|
153
|
+
imageOpacity: 0.6
|
|
154
|
+
foreground: imagens/pessoa.svg
|
|
155
|
+
titleSize: 300
|
|
156
|
+
kicker: "titleSize: 300"
|
|
157
|
+
title: "TUDO\nJUNTO"
|
|
158
|
+
subtitle: Fundo, transparência, recorte e texto maior.
|
|
159
|
+
caption: TUDO JUNTO
|
|
160
|
+
|
|
161
|
+
- layout: scenography
|
|
162
|
+
scene: orbit
|
|
163
|
+
titleSize: 110
|
|
164
|
+
kicker: "titleSize: 110"
|
|
165
|
+
title: "Texto menor, mais respiro"
|
|
166
|
+
subtitle: Sem titleSize, cada composição usa o seu tamanho padrão.
|
|
167
|
+
caption: TAMANHO DO TEXTO
|
|
168
|
+
|
|
169
|
+
- layout: end
|
|
170
|
+
title: Agora é com você
|
|
171
|
+
subtitle: Inserir, Texto no cenário. Depois é só escolher a composição.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080" width="1920" height="1080">
|
|
2
|
+
<!-- fundo de exemplo do deck "Texto no cenário": uma cidade ao entardecer (troque por uma foto sua) -->
|
|
3
|
+
<defs>
|
|
4
|
+
<linearGradient id="ceu" x1="0" y1="0" x2="0" y2="1">
|
|
5
|
+
<stop offset="0" stop-color="#241a4f"/>
|
|
6
|
+
<stop offset=".55" stop-color="#b8517a"/>
|
|
7
|
+
<stop offset=".8" stop-color="#ffb070"/>
|
|
8
|
+
</linearGradient>
|
|
9
|
+
<pattern id="janelas" width="36" height="44" patternUnits="userSpaceOnUse">
|
|
10
|
+
<rect x="8" y="10" width="14" height="18" fill="#ffd98a" opacity=".75"/>
|
|
11
|
+
</pattern>
|
|
12
|
+
</defs>
|
|
13
|
+
<rect width="1920" height="1080" fill="url(#ceu)"/>
|
|
14
|
+
<circle cx="1380" cy="700" r="170" fill="#ffe2a6" opacity=".9"/>
|
|
15
|
+
<g fill="#3a2350">
|
|
16
|
+
<rect x="0" y="640" width="220" height="440"/><rect x="240" y="520" width="170" height="560"/>
|
|
17
|
+
<rect x="430" y="700" width="260" height="380"/><rect x="700" y="430" width="150" height="650"/>
|
|
18
|
+
<rect x="870" y="610" width="230" height="470"/><rect x="1120" y="540" width="190" height="540"/>
|
|
19
|
+
<rect x="1330" y="760" width="210" height="320"/><rect x="1560" y="480" width="160" height="600"/>
|
|
20
|
+
<rect x="1740" y="660" width="180" height="420"/>
|
|
21
|
+
</g>
|
|
22
|
+
<g fill="#1d1230">
|
|
23
|
+
<rect x="100" y="780" width="260" height="300"/><rect x="560" y="820" width="210" height="260"/>
|
|
24
|
+
<rect x="980" y="760" width="240" height="320"/><rect x="1450" y="840" width="300" height="240"/>
|
|
25
|
+
</g>
|
|
26
|
+
<g fill="url(#janelas)">
|
|
27
|
+
<rect x="240" y="520" width="170" height="560"/><rect x="700" y="430" width="150" height="650"/>
|
|
28
|
+
<rect x="1120" y="540" width="190" height="540"/><rect x="1560" y="480" width="160" height="600"/>
|
|
29
|
+
</g>
|
|
30
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080" width="1920" height="1080">
|
|
2
|
+
<!-- recorte de exemplo (fundo transparente): uma pessoa em pé, à direita. Fica na frente das letras (foreground).
|
|
3
|
+
Para uma foto sua, recorte a pessoa num editor e salve como PNG transparente do mesmo tamanho do slide. -->
|
|
4
|
+
<defs>
|
|
5
|
+
<linearGradient id="luz" x1="0" y1="0" x2="1" y2="0">
|
|
6
|
+
<stop offset="0" stop-color="#2a2238"/>
|
|
7
|
+
<stop offset=".75" stop-color="#1a1424"/>
|
|
8
|
+
<stop offset="1" stop-color="#ff9a6b"/>
|
|
9
|
+
</linearGradient>
|
|
10
|
+
</defs>
|
|
11
|
+
<g fill="url(#luz)">
|
|
12
|
+
<ellipse cx="1470" cy="455" rx="62" ry="74"/>
|
|
13
|
+
<path d="M1452 520h40l10 30c70 10 118 40 130 110l40 250c6 40-40 50-52 12l-40-190-10 398h-68l-20-300-20 300h-68l-12-398-40 190c-12 38-58 28-52-12l40-250c12-70 60-100 122-110z"/>
|
|
14
|
+
</g>
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
title: Texto no cenário e matemática
|
|
2
|
+
id: cenario-e-ciencia
|
|
3
|
+
theme: aurora
|
|
4
|
+
motion: none
|
|
5
|
+
slides:
|
|
6
|
+
- layout: scenography
|
|
7
|
+
scene: stage
|
|
8
|
+
kicker: IDEIAS QUE OCUPAM ESPAÇO
|
|
9
|
+
title: "ALÉM DO\nÓBVIO"
|
|
10
|
+
subtitle: O texto também faz parte da história.
|
|
11
|
+
caption: SAGADECK / ESTUDO 01
|
|
12
|
+
deco: none
|
|
13
|
+
- layout: scenography
|
|
14
|
+
scene: floor
|
|
15
|
+
kicker: UMA NOVA PERSPECTIVA
|
|
16
|
+
title: "NOVOS\nCAMINHOS"
|
|
17
|
+
caption: SAGADECK / ESTUDO 02
|
|
18
|
+
deco: none
|
|
19
|
+
- layout: scenography
|
|
20
|
+
scene: signs
|
|
21
|
+
kicker: PRÓXIMA PARADA
|
|
22
|
+
title: "IDEIAS\nEM CENA"
|
|
23
|
+
subtitle: Mensagens que pertencem ao lugar.
|
|
24
|
+
caption: SAGADECK / ESTUDO 03
|
|
25
|
+
deco: none
|
|
26
|
+
- layout: science
|
|
27
|
+
title: A onda e sua derivada
|
|
28
|
+
equations:
|
|
29
|
+
- label: Função
|
|
30
|
+
latex: 'f(x)=\sin(x)'
|
|
31
|
+
- label: Derivada
|
|
32
|
+
latex: 'f\prime(x)=\cos(x)'
|
|
33
|
+
- label: Identidade
|
|
34
|
+
latex: '\sin^2(x)+\cos^2(x)=1'
|
|
35
|
+
plot:
|
|
36
|
+
preset: wave
|
|
37
|
+
notes: Arraste uma área do gráfico para dar zoom. Passe o mouse para consultar os valores.
|
|
38
|
+
- layout: science
|
|
39
|
+
title: Matemática que você pode explorar
|
|
40
|
+
equations:
|
|
41
|
+
- label: Raio
|
|
42
|
+
latex: 'r=\sqrt{x^2+y^2}'
|
|
43
|
+
- label: Superfície
|
|
44
|
+
latex: 'z=\sin(r)'
|
|
45
|
+
plot:
|
|
46
|
+
preset: surface
|
|
47
|
+
notes: Arraste para girar. Use a roda do mouse para aproximar.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Ensaio de aula de APIs de IA: roda contra a API de mentira, no ambiente embutido ENSAIO do Studio
|
|
2
|
+
# (biblioteca → Nova → "Exemplo: aula de APIs ao vivo", ou `sagadeck ensaio-api`).
|
|
3
|
+
# Serve de modelo: troque as URLs e os caminhos $.… pelos do seu serviço e cadastre os seus ambientes
|
|
4
|
+
# no Studio (Inserir → Ambientes), que grava em ~/.sagadeck/ambientes.yaml. Veja "Slide api" em docs/REFERENCIA.md.
|
|
5
|
+
title: "Ensaio: APIs de IA ao vivo"
|
|
6
|
+
theme: sinal
|
|
7
|
+
author: Seu nome
|
|
8
|
+
duration: 30
|
|
9
|
+
slides:
|
|
10
|
+
- layout: cover
|
|
11
|
+
kicker: Ensaio
|
|
12
|
+
title: APIs de IA, ==ao vivo==
|
|
13
|
+
subtitle: Do token à resposta, executando na frente de todo mundo
|
|
14
|
+
notes: |
|
|
15
|
+
Este deck roda contra uma API de mentira (o ambiente ENSAIO, que o Studio sobe sozinho). Apresente e clique em Executar em cada slide.
|
|
16
|
+
Se você já tem ambientes seus, clique no selo do slide (DEV, HOM…) e escolha ENSAIO.
|
|
17
|
+
Tudo funciona igual com o serviço de verdade: troque os endereços em Inserir → Ambientes.
|
|
18
|
+
|
|
19
|
+
- layout: api
|
|
20
|
+
id: identity
|
|
21
|
+
kicker: Passo 1 · Identity
|
|
22
|
+
title: Primeiro, o ==token==
|
|
23
|
+
text: Toda chamada leva um JWT que vale 30 minutos
|
|
24
|
+
request:
|
|
25
|
+
method: POST
|
|
26
|
+
url: "{{identity}}"
|
|
27
|
+
auth: false
|
|
28
|
+
body: { client_id: "{{client_id}}", client_secret: "{{secret.client_secret}}" }
|
|
29
|
+
token: "$.data.token"
|
|
30
|
+
notes: |
|
|
31
|
+
Mostre o corpo: o client_secret aparece como {{secret.client_secret}} — o valor fica no ambiente, nunca no slide.
|
|
32
|
+
Execute: o JWT aparece decodificado, com a contagem regressiva. Daqui para frente, todo slide usa este token (olhe o final ••••).
|
|
33
|
+
|
|
34
|
+
- layout: api
|
|
35
|
+
id: llm
|
|
36
|
+
kicker: Passo 2 · LLM
|
|
37
|
+
title: A pergunta mais ==simples==
|
|
38
|
+
request:
|
|
39
|
+
method: POST
|
|
40
|
+
url: "{{base}}/sync"
|
|
41
|
+
body: { messages: [ { role: user, content: "O que é RAG, em uma frase?" } ] }
|
|
42
|
+
answer: "$.choices[0].message.content"
|
|
43
|
+
notes: Edite a pergunta na hora (aba Corpo) e execute de novo. Mostre as abas curl e Python.
|
|
44
|
+
|
|
45
|
+
- layout: api
|
|
46
|
+
id: openrouter-nemotron
|
|
47
|
+
kicker: OpenRouter (real)
|
|
48
|
+
title: Pergunte ao ==Nemotron==
|
|
49
|
+
text: Chamada real ao modelo gratuito NVIDIA Nemotron pelo OpenRouter
|
|
50
|
+
request:
|
|
51
|
+
method: POST
|
|
52
|
+
url: "{{base}}/chat/completions"
|
|
53
|
+
auth: false
|
|
54
|
+
headers:
|
|
55
|
+
Authorization: "Bearer {{secret.openrouter_api_key}}"
|
|
56
|
+
X-Title: SagaDeck
|
|
57
|
+
body:
|
|
58
|
+
model: nvidia/nemotron-3-super-120b-a12b:free
|
|
59
|
+
max_tokens: 350
|
|
60
|
+
messages:
|
|
61
|
+
- role: user
|
|
62
|
+
content: "Explique o que é uma API em uma frase, em português."
|
|
63
|
+
answer: "$.choices[0].message.content"
|
|
64
|
+
notes: |
|
|
65
|
+
Esta chamada acessa o OpenRouter de verdade com um modelo gratuito compatível com Chat Completions.
|
|
66
|
+
No selo de ambiente, escolha OPENROUTER.
|
|
67
|
+
A chave não fica no deck: defina OPENROUTER_API_KEY no processo que inicia o Studio e reinicie-o.
|
|
68
|
+
Edite a pergunta na aba Corpo e execute novamente para testar o comportamento do modelo.
|
|
69
|
+
|
|
70
|
+
- layout: api
|
|
71
|
+
id: workflow
|
|
72
|
+
kicker: Passo 3 · Workflow
|
|
73
|
+
title: Inicia e ==acompanha== até terminar
|
|
74
|
+
text: O início devolve só o código da execução; a consulta repete até FINISHED
|
|
75
|
+
mode: polling
|
|
76
|
+
tab: python-comentado
|
|
77
|
+
request: { url: "{{base}}/start", body: { workflow: "{{wf}}", input: { path_id: "store/contrato.txt" } } }
|
|
78
|
+
polling: { id: "$.executionId", check: { url: "{{base}}/status/{{id}}" }, status: "$.status", done: [FINISHED], failed: [ERROR], interval: 0.8 }
|
|
79
|
+
steps: "$.responses"
|
|
80
|
+
stepText: "$.output"
|
|
81
|
+
notes: Deixe na aba Python comentado e execute — o laço while acende a cada consulta, enquanto a linha do tempo cresce.
|
|
82
|
+
|
|
83
|
+
- layout: api
|
|
84
|
+
id: stream
|
|
85
|
+
kicker: Passo 4 · Streaming
|
|
86
|
+
title: A resposta chega ==aos poucos==
|
|
87
|
+
mode: stream
|
|
88
|
+
request: { method: POST, url: "{{base}}/stream", body: { stream: true } }
|
|
89
|
+
notes: "Compare com o síncrono: aqui o texto aparece enquanto é gerado."
|
|
90
|
+
|
|
91
|
+
- layout: api
|
|
92
|
+
id: upload
|
|
93
|
+
kicker: Passo 5 · FileManager
|
|
94
|
+
title: Sobe o arquivo, volta o ==path_id==
|
|
95
|
+
file: contrato.txt
|
|
96
|
+
request: { url: "{{base}}/upload", form: { file: "@file", pasta: workshop } }
|
|
97
|
+
save: { path_id: "$.path_id" }
|
|
98
|
+
notes: Arraste outro arquivo no slide se quiser. O path_id fica guardado para os próximos slides.
|
|
99
|
+
|
|
100
|
+
- layout: api
|
|
101
|
+
id: ocr
|
|
102
|
+
kicker: Passo 6 · OCR
|
|
103
|
+
title: Lendo pelo ==path_id==
|
|
104
|
+
request: { url: "{{base}}/ocr", body: { path_id: "{{path_id}}" } }
|
|
105
|
+
answer: "$.text"
|
|
106
|
+
notes: "Mostre que {{path_id}} veio do slide anterior (aba curl: já com o valor)."
|
|
107
|
+
|
|
108
|
+
- layout: api
|
|
109
|
+
id: indexador
|
|
110
|
+
kicker: Passo 7 · Indexador
|
|
111
|
+
title: Planilha ==linha a linha==
|
|
112
|
+
tab: fields
|
|
113
|
+
request: { url: "{{base}}/index", body: { path_id: "{{path_id}}", mode: rows, sheet: { header_row: 1 }, chunk_size: 0 } }
|
|
114
|
+
fields:
|
|
115
|
+
"$.mode": "rows: cada linha vira um documento; pdf: o arquivo inteiro, em pedaços"
|
|
116
|
+
"$.sheet.header_row": "linha do cabeçalho (começa em 1): as colunas viram metadados"
|
|
117
|
+
"$.chunk_size": "com rows, tem que ser 0 — qualquer outro valor faz a indexação falhar"
|
|
118
|
+
"$.path_id": "o que o FileManager devolveu"
|
|
119
|
+
answer: "$.documents"
|
|
120
|
+
notes: "Mude chunk_size para 800 na aba Corpo e execute: a indexação falha. É a combinação que a documentação não conta."
|
|
121
|
+
|
|
122
|
+
- layout: api
|
|
123
|
+
id: embeddings
|
|
124
|
+
kicker: Passo 8 · Embeddings
|
|
125
|
+
title: Qual frase fica ==mais perto==?
|
|
126
|
+
request: { url: "{{base}}/embeddings", body: { model: emb, input: "{{text}}" } }
|
|
127
|
+
similarity:
|
|
128
|
+
reference: Quero abrir uma conta no banco
|
|
129
|
+
texts: [ "Vai chover amanhã em São Paulo?", "Como faço para abrir uma conta?", "Abrir conta no banco hoje" ]
|
|
130
|
+
notes: "Peça frases para a plateia e escreva na aba Frases."
|
|
131
|
+
|
|
132
|
+
- layout: api
|
|
133
|
+
id: tts
|
|
134
|
+
kicker: Passo 9 · Voz
|
|
135
|
+
title: Texto que ==fala==
|
|
136
|
+
audio: fala.wav
|
|
137
|
+
request: { url: "{{base}}/tts", body: { text: "Bom dia, pessoal" } }
|
|
138
|
+
|
|
139
|
+
- layout: api
|
|
140
|
+
id: stt
|
|
141
|
+
kicker: Passo 10 · Escuta
|
|
142
|
+
title: Fala que vira ==texto==
|
|
143
|
+
mic: true
|
|
144
|
+
request: { url: "{{base}}/stt", form: { audio: "@file", idioma: pt-BR } }
|
|
145
|
+
answer: "$.text"
|
|
146
|
+
notes: "Clique em Gravar, fale, clique em Parar: ele envia sozinho."
|
|
147
|
+
|
|
148
|
+
- layout: api
|
|
149
|
+
id: tempo-real
|
|
150
|
+
kicker: Passo 11 · Tempo real
|
|
151
|
+
title: Conversa por ==voz==, ao vivo
|
|
152
|
+
mode: realtime
|
|
153
|
+
realtime:
|
|
154
|
+
url: "{{ws}}/realtime"
|
|
155
|
+
open: [ { type: session.update, session: { voice: alloy, instructions: "Responda em português, curto." } } ]
|
|
156
|
+
notes: "Conecte, clique em Falar, fale e clique em Parar. Mostre a aba Mensagens: cada evento do WebSocket, nos dois sentidos."
|
|
157
|
+
|
|
158
|
+
- layout: end
|
|
159
|
+
title: Obrigado.
|
|
160
|
+
subtitle: Perguntas?
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
title: Apresentação Alegre e Visual
|
|
2
|
+
theme: rabisco
|
|
3
|
+
duration: 15
|
|
4
|
+
slides:
|
|
5
|
+
- layout: cover
|
|
6
|
+
kicker: Ideias Vivas · Sem Sono
|
|
7
|
+
title: Como Criar Slides Bonitinhos & Visuais
|
|
8
|
+
subtitle: Menos texto longo, muito mais impacto e cores alegres
|
|
9
|
+
author: SagaDeck Studio
|
|
10
|
+
- layout: stats
|
|
11
|
+
kicker: Métricas em Destaque
|
|
12
|
+
title: O Poder dos Números Visuais
|
|
13
|
+
stats:
|
|
14
|
+
- value: 98.7%
|
|
15
|
+
label: Retenção da Atenção
|
|
16
|
+
trend: +34%
|
|
17
|
+
trendUp: true
|
|
18
|
+
icon: heart
|
|
19
|
+
text: Público conectado do início ao fim
|
|
20
|
+
- value: 4.8x
|
|
21
|
+
label: Mais Rápido de Ler
|
|
22
|
+
trend: recorde
|
|
23
|
+
trendUp: true
|
|
24
|
+
icon: zap
|
|
25
|
+
text: Zero cansaço visual
|
|
26
|
+
- value: 2.100+
|
|
27
|
+
label: Ícones Disponíveis
|
|
28
|
+
trend: ilimitado
|
|
29
|
+
trendUp: true
|
|
30
|
+
icon: sparkles
|
|
31
|
+
text: Elementos gráficos prontos
|
|
32
|
+
- layout: steps
|
|
33
|
+
kicker: Fluxo Visual
|
|
34
|
+
title: Processo Simples em 3 Etapas
|
|
35
|
+
steps:
|
|
36
|
+
- stepNum: 1
|
|
37
|
+
title: Rascunho
|
|
38
|
+
text: Escolha o tema Rabisco ou Oceano
|
|
39
|
+
icon: pen-tool
|
|
40
|
+
tag: 1 Minuto
|
|
41
|
+
- stepNum: 2
|
|
42
|
+
title: Visualizar
|
|
43
|
+
text: Troque parágrafos por cards e métricas
|
|
44
|
+
icon: layout-grid
|
|
45
|
+
tag: Auto-Fit
|
|
46
|
+
- stepNum: 3
|
|
47
|
+
title: Apresentar
|
|
48
|
+
text: Entregue um show no palco sem sono
|
|
49
|
+
icon: smile
|
|
50
|
+
tag: Aplausos
|
|
51
|
+
- layout: cards
|
|
52
|
+
kicker: Cartões Inteligentes
|
|
53
|
+
title: Widgets que Eliminam Textão
|
|
54
|
+
cols: 3
|
|
55
|
+
items:
|
|
56
|
+
- icon: check-circle-2
|
|
57
|
+
badge: Recomendado
|
|
58
|
+
title: Checklist Visual
|
|
59
|
+
text: Substitui listas sem graça por confirmações visuais.
|
|
60
|
+
check: true
|
|
61
|
+
checkText: Pronto para uso
|
|
62
|
+
- icon: target
|
|
63
|
+
title: Meta de Conclusão
|
|
64
|
+
text: Progresso visual fácil de acompanhar.
|
|
65
|
+
progress: 88
|
|
66
|
+
progressLabel: Meta Atingida
|
|
67
|
+
- icon: award
|
|
68
|
+
title: Avaliação do Público
|
|
69
|
+
text: Nota máxima dada pela audiência.
|
|
70
|
+
rating: 5
|
|
71
|
+
ratingLabel: 5.0 no G2
|
|
72
|
+
tags:
|
|
73
|
+
- Alegre
|
|
74
|
+
- Dinâmico
|
|
75
|
+
- Sem Sono
|