- JWT auth with bcrypt password hashing, cookie sessions, forgot/reset password - Per-user encrypted credential storage (Redis + AES-256-GCM) for all 9 platforms - Usage tracking with monthly limits per plan (free/starter/growth/enterprise) - Invoice generation and retrieval (admin + user views) - Admin panel with customer listing (role-based access) - Web app UI at app.squaremcp.com — login, dashboard, connections, usage, invoices - Unified auth middleware: API key, OAuth Bearer, and JWT cookie support - Facebook Graph API fixes: published_posts endpoint, photo/video post support - TikTok sandbox compliance: SELF_ONLY privacy for unaudited apps - URL verification files for TikTok app review
114 lines
3.1 KiB
TypeScript
114 lines
3.1 KiB
TypeScript
import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion";
|
|
import { COLORS, FONT, SPRING_CFG } from "../../styles";
|
|
|
|
const TOOL_LABELS = [
|
|
"Email",
|
|
"Notes",
|
|
"CRM",
|
|
"LinkedIn",
|
|
"X",
|
|
"WhatsApp",
|
|
"Docs",
|
|
"Sheets",
|
|
"Tickets",
|
|
"Calendar",
|
|
"DB",
|
|
"API",
|
|
];
|
|
|
|
export const TikTokHook = () => {
|
|
const frame = useCurrentFrame();
|
|
const { fps } = useVideoConfig();
|
|
const terminalIn = spring({ fps, frame, config: SPRING_CFG });
|
|
const gridIn = spring({ fps, frame: Math.max(0, frame - 18), config: SPRING_CFG });
|
|
const captionIn = interpolate(frame, [20, 34], [0, 1], { extrapolateRight: "clamp" });
|
|
|
|
return (
|
|
<AbsoluteFill style={{ padding: 72 }}>
|
|
<div
|
|
style={{
|
|
marginTop: 120,
|
|
borderRadius: 32,
|
|
border: `1px solid ${COLORS.borderBlue}`,
|
|
background: "rgba(7, 8, 18, 0.92)",
|
|
boxShadow: `0 20px 60px ${COLORS.accentGlow}`,
|
|
padding: "28px 32px",
|
|
opacity: terminalIn,
|
|
transform: `translateY(${(1 - terminalIn) * 80}px)`,
|
|
}}
|
|
>
|
|
<div style={{ display: "flex", gap: 12, marginBottom: 26 }}>
|
|
{["#ff5f57", "#febc2e", "#28c840"].map((dot) => (
|
|
<div key={dot} style={{ width: 14, height: 14, borderRadius: 999, background: dot }} />
|
|
))}
|
|
</div>
|
|
<div
|
|
style={{
|
|
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
fontWeight: 700,
|
|
fontSize: 44,
|
|
color: COLORS.accentLight,
|
|
letterSpacing: -1.2,
|
|
}}
|
|
>
|
|
{"> connect squaremcp"}
|
|
<span style={{ color: COLORS.text, opacity: (frame % 20) < 10 ? 1 : 0 }}>|</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
style={{
|
|
marginTop: 48,
|
|
display: "grid",
|
|
gridTemplateColumns: "repeat(3, 1fr)",
|
|
gap: 18,
|
|
opacity: gridIn,
|
|
transform: `scale(${0.9 + gridIn * 0.1})`,
|
|
}}
|
|
>
|
|
{TOOL_LABELS.map((label, index) => (
|
|
<div
|
|
key={label}
|
|
style={{
|
|
borderRadius: 24,
|
|
border: `1px solid ${COLORS.borderBlue}`,
|
|
background: index % 2 === 0 ? "rgba(18, 18, 31, 0.95)" : "rgba(10, 17, 38, 0.92)",
|
|
padding: "26px 16px",
|
|
minHeight: 112,
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
color: COLORS.text,
|
|
fontFamily: FONT,
|
|
fontWeight: 700,
|
|
fontSize: 28,
|
|
boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.03)",
|
|
}}
|
|
>
|
|
{label}
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div
|
|
style={{
|
|
marginTop: "auto",
|
|
marginBottom: 68,
|
|
fontFamily: FONT,
|
|
fontSize: 54,
|
|
fontWeight: 800,
|
|
color: COLORS.text,
|
|
lineHeight: 1.05,
|
|
letterSpacing: -1.8,
|
|
opacity: captionIn,
|
|
transform: `translateY(${(1 - captionIn) * 40}px)`,
|
|
}}
|
|
>
|
|
One API key.
|
|
<br />
|
|
One workflow layer.
|
|
</div>
|
|
</AbsoluteFill>
|
|
);
|
|
};
|