feature: new dashboard workos auth for dashboard login, dashboard optional in site config, sync server for dashboard, workos and dashboard docs updated

This commit is contained in:
Wayne Sutton
2025-12-29 22:11:52 -08:00
parent f6c9478c9d
commit e8d09fcce2
47 changed files with 15058 additions and 193 deletions

View File

@@ -13,6 +13,7 @@ interface ContactFormProps {
// Contact form component
// Displays a form with name, email, and message fields
// Submits to Convex which sends email via AgentMail
// Includes honeypot field for bot protection
export default function ContactForm({
source,
title,
@@ -21,6 +22,7 @@ export default function ContactForm({
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
const [honeypot, setHoneypot] = useState(""); // Honeypot field for bot detection
const [status, setStatus] = useState<"idle" | "loading" | "success" | "error">("idle");
const [statusMessage, setStatusMessage] = useState("");
@@ -36,6 +38,17 @@ export default function ContactForm({
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
// Honeypot check: if filled, silently reject (bot detected)
if (honeypot) {
// Pretend success to not alert the bot
setStatus("success");
setStatusMessage("Thanks for your message! We'll get back to you soon.");
setName("");
setEmail("");
setMessage("");
return;
}
// Basic validation
if (!name.trim()) {
setStatus("error");
@@ -103,6 +116,31 @@ export default function ContactForm({
</div>
) : (
<form onSubmit={handleSubmit} className="contact-form__form">
{/* Honeypot field: hidden from humans, visible to bots */}
<div
aria-hidden="true"
style={{
position: "absolute",
left: "-9999px",
top: "-9999px",
opacity: 0,
pointerEvents: "none",
height: 0,
overflow: "hidden",
}}
>
<label htmlFor="contact-website">Website</label>
<input
id="contact-website"
type="text"
name="website"
tabIndex={-1}
autoComplete="off"
value={honeypot}
onChange={(e) => setHoneypot(e.target.value)}
/>
</div>
<div className="contact-form__field">
<label htmlFor="contact-name" className="contact-form__label">
Name

View File

@@ -14,6 +14,7 @@ interface NewsletterSignupProps {
// Newsletter signup component
// Displays email input form for newsletter subscriptions
// Integrates with Convex backend for subscriber management
// Includes honeypot field for bot protection
export default function NewsletterSignup({
source,
postSlug,
@@ -21,6 +22,7 @@ export default function NewsletterSignup({
description,
}: NewsletterSignupProps) {
const [email, setEmail] = useState("");
const [honeypot, setHoneypot] = useState(""); // Honeypot field for bot detection
const [status, setStatus] = useState<
"idle" | "loading" | "success" | "error"
>("idle");
@@ -49,6 +51,15 @@ export default function NewsletterSignup({
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
// Honeypot check: if filled, silently reject (bot detected)
if (honeypot) {
// Pretend success to not alert the bot
setStatus("success");
setMessage("Thanks for subscribing!");
setEmail("");
return;
}
if (!email.trim()) {
setStatus("error");
setMessage("Please enter your email.");
@@ -88,6 +99,31 @@ export default function NewsletterSignup({
<p className="newsletter-signup__success">{message}</p>
) : (
<form onSubmit={handleSubmit} className="newsletter-signup__form">
{/* Honeypot field: hidden from humans, visible to bots */}
<div
aria-hidden="true"
style={{
position: "absolute",
left: "-9999px",
top: "-9999px",
opacity: 0,
pointerEvents: "none",
height: 0,
overflow: "hidden",
}}
>
<label htmlFor={`newsletter-fax-${source}`}>Fax</label>
<input
id={`newsletter-fax-${source}`}
type="text"
name="fax"
tabIndex={-1}
autoComplete="off"
value={honeypot}
onChange={(e) => setHoneypot(e.target.value)}
/>
</div>
<input
type="email"
value={email}