WorkProduction
Pyris Consulting
A consulting-firm website where the front door is a tool-using conversation, the blog remains on the apex, and a paid diagnostic cannot reserve time before payment.
Pyris Consulting is my operations-consulting firm and the first production system I built entirely through AI-augmented development.
The visible artifact is a website. The actual product is the path from a stranger arriving with an ill-defined operational problem to a useful conversation, a real calendar event, and—on one door—a verified payment. That path crosses a React single-page application, an Astro publishing system, a Node server, Google Calendar and Gmail, Stripe, Supabase, and one tool-using agent named Cyris.
The design problem was never “put a chatbot on a consulting site.” It was making one public property legible to people, search engines, AI crawlers, and payment infrastructure without letting the most interpretive component become the authority over money or identity.
One domain, two applications
The marketing surface is a React single-page application. The practitioner blog is a separate Astro application with its own browser-based editor and deployment path. Publicly they appear under one domain: pyrisconsulting.com/blog/* is reverse-proxied through the main server rather than split onto a subdomain.
That choice created two classes of problems.
First, mount order became architecture. A global JSON body parser once consumed analytics POST bodies before the proxy could forward them. Hashed analytics scripts fell through to the SPA catch-all and returned HTML with a successful status, which the browser then tried to execute as JavaScript. The correction was not a retry. It was a shared skip-set and proxy-set that describe the same boundary.
Second, an SPA lies to crawlers by default. Every route initially served the same HTML shell with the homepage canonical, title, and social tags. The browser later painted the correct page, but Google and link unfurls had already read the wrong document.
The server now rewrites the shell from a route map before it leaves. Canonical URL, title, description, and social metadata travel with the requested path. Tests prove that the route metadata is a subset of the canonical map so a new page cannot quietly become an orphaned public identity.
Four doors, one business surface
Cyris occupies four public entry points:
· Homepage intake saves a lead and can book a no-cost twenty-minute discovery call.
· Operations Flow Check takes a $1,500 card payment before offering a ninety-minute calendar hold.
· Operations Audit conducts a twelve-determination maturity interview and returns the read without a results wall.
· AI Readiness reconstructs real processes and team posture, then returns a readiness read without naming software or manufacturing a failing grade.
All four doors share one server loop. The route context selects a prompt and a tool set, but it is never treated as an authorization boundary. A visitor can omit a client-supplied string. Security has to survive that omission.
The agent is described separately in the Cyris Work entry. On this page, the important fact is that the site’s primary conversion mechanism is a live business process rather than a form.
Payment before scarcity
The paid diagnostic reverses the usual consultation funnel.
The original flow booked time and then sent a payment link. That let a visitor reserve a scarce ninety-minute slot without paying. The live system creates a Stripe Checkout session first. Stripe’s signed webhook writes the paid fact. Only then does the booking capability become available.
The model is not the cashier. It cannot declare the buyer paid because a message says so, because the return URL looks right, or because it called a tool with confidence. Payment is a server-owned fact written by Stripe.
The return path carries a resume token back into an already-open conversation. Reschedule updates the same Calendar event in place. Cancel never automatically refunds. The old payment-link route and the test-only bypass used for live walks were deleted so a stale environment variable cannot quietly reopen a second money path.
Possession, not a guessed identity
The first booking tools trusted an email address supplied during conversation. A public user could ask the agent to find a booking by email, receive an event identifier and personal details, then cancel that raw identifier. The shared tool layer made the problem larger than one route.
The replacement is possession-proof. A confirmation email contains a signed manage token. The server validates that token and becomes the only writer of the verified event id and verified email. Tool schemas accept no attacker-aimable cancel target. The model can conduct the conversation; it cannot nominate the victim.
That distinction also defeated two plausible review fixes. Removing cancel tools from the paid door did not help because an attacker could omit the door label and fall through to the homepage tool set. Gating cancel on state written by unauthenticated find merely moved the trust error. The close had to remove attacker choice from the tool boundary itself.
Search and answer-engine infrastructure
Pyris publishes both for conventional search and for systems that synthesize answers.
The live server exposes route-correct canonicals, a sitemap, structured data, robots.txt, and an llms.txt description of the firm’s services. The Astro blog contributes practitioner articles with visible FAQs and matching BlogPosting and FAQPage structures. The schema follows visible content rather than becoming a second marketing surface that claims what the page does not say.
The system is measured in named wires. On August 31, 2026, the apex sitemap held five locations, the blog sitemap held seven, six of six mapped SPA routes returned the expected live title and canonical, and the public health endpoint reported the process up. Those counts describe different objects. They are not added into “eighteen pages of SEO.”
The deployed URL is the gate
Several of the system’s sharpest defects passed local builds and written review.
A Node 20 production host crash-looped against a database client that required Node 22 while two agent loops referenced a model retired the day before. A wall-mounted calendar hung for two weeks after a security header severed the Google sign-in popup channel. The first diagnosis blamed Content Security Policy; the actual cause was Cross-Origin-Opener-Policy, and the fix belonged on one path rather than site-wide.
The operating rule that came out of those incidents is blunt:
Built green is not works live.
A build, suite, or review can prove something useful about an artifact. None of them prove the behavior at the deployed boundary. Every meaningful ship ends by loading the real URL and walking the actual path.
Where it stands
Pyris is live. The React application and Node API run on Railway. The Astro blog runs on Vercel under the apex proxy. Four Cyris doors are public. The paid Flow Check charges real cards before booking. The blog publishes through a browser-based Git-backed editor. The old partner workspace, Polarity, was deleted from the product while its five database tables remain intentionally untouched.
The August 31 brief names open work plainly: a pre-campaign rate-limit increase, one remaining identity-binding choke point, and a /builds page blocked on missing prices. The several-hundred-contractor campaign remains unsent.
Pyris is not interesting because every edge is closed. It is interesting because the system knows the difference between a live property, a proven mechanism, a killed path, and a promise still waiting for evidence.
Provenance
- Published
- 2026-08-31 — generated from commit history, not maintained by hand
- Revised
- 2026-08-31 — 1 revision. Status changes are commits, never a typed field.
