S
SolidJS•2d ago
MaveriX89

renderToString in Elysia BFF Layer

Random question, I have a Solid SPA with a BFF server (implemented using Elysia) -- so this is not Solid Start. This all lives under a single repository with the following root, high-level structure:
- shared (contains things shared across both Elysia BFF and Solid SPA)
- server (Elysia BFF: contains only normal TypeScript files)
- src (SolidJS SPA: contains TSX files)
- tsconfig.json (TS config for entire repo)
- vite.config.ts (Vite config for SPA)
- shared (contains things shared across both Elysia BFF and Solid SPA)
- server (Elysia BFF: contains only normal TypeScript files)
- src (SolidJS SPA: contains TSX files)
- tsconfig.json (TS config for entire repo)
- vite.config.ts (Vite config for SPA)
I am in the process of integrating an email verification feature in my Elysia server. I am sending the email using Resend like so:
// sendVerificationEmail.ts
resendClient.emails.send({
from: 'Onboarding <[email protected]>',
to: user.email,
subject: 'Verify your email',
html: `<p>Click <a href="${url}">here</a> to verify your email.</p>`
});
// sendVerificationEmail.ts
resendClient.emails.send({
from: 'Onboarding <[email protected]>',
to: user.email,
subject: 'Verify your email',
html: `<p>Click <a href="${url}">here</a> to verify your email.</p>`
});
The question I have is related to that html field. I would like to use a SolidJS component to layout the HTML structure of the email content leveraging the renderToString Solid API. This would add a single .tsx file in that layer. That'll convert things to the following:
// VerifyEmail.tsx (note the TSX extension)
import { renderToString } from "solid-js/web"

export const Email = (props: { url: string }) => {
return (
<html>
<body>
<h2>Onboarding</h2>
<p>
Click <a href={props.url}>here</a> to verify your email.
</p>
</body>
</html>
)
}

export const getEmailTemplate = (url: string) => renderToString(() => <Email url={url} />)

// sendVerificationEmail.ts
resendClient.emails.send({
from: 'Onboarding <[email protected]>',
to: user.email,
subject: 'Verify your email',
html: getEmailTemplate(url);
});
// VerifyEmail.tsx (note the TSX extension)
import { renderToString } from "solid-js/web"

export const Email = (props: { url: string }) => {
return (
<html>
<body>
<h2>Onboarding</h2>
<p>
Click <a href={props.url}>here</a> to verify your email.
</p>
</body>
</html>
)
}

export const getEmailTemplate = (url: string) => renderToString(() => <Email url={url} />)

// sendVerificationEmail.ts
resendClient.emails.send({
from: 'Onboarding <[email protected]>',
to: user.email,
subject: 'Verify your email',
html: getEmailTemplate(url);
});
I put my component in a separate module within my Elysia BFF layer and imported the getEmailTemplate in my module that sends the email. But when I run the code, I get the following error:
ReferenceError: React is not defined
at <anonymous> (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/server/lib/Email.tsx:16:71)
at <anonymous> (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/node_modules/solid-js/web/dist/server.js:559:34)
at createRoot (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/node_modules/solid-js/dist/server.js:58:14)
at renderToString (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/node_modules/solid-js/web/dist/server.js:557:14)
at <anonymous> (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/server/lib/auth.ts:53:15)
at sendVerificationEmail (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/server/lib/auth.ts:48:37)
at <anonymous> (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/node_modules/better-auth/dist/api/index.mjs:238:52)
ReferenceError: React is not defined
at <anonymous> (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/server/lib/Email.tsx:16:71)
at <anonymous> (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/node_modules/solid-js/web/dist/server.js:559:34)
at createRoot (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/node_modules/solid-js/dist/server.js:58:14)
at renderToString (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/node_modules/solid-js/web/dist/server.js:557:14)
at <anonymous> (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/server/lib/auth.ts:53:15)
at sendVerificationEmail (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/server/lib/auth.ts:48:37)
at <anonymous> (/Users/dsanchez/Developer/github/dsanchez/template-better-auth-solidjs/node_modules/better-auth/dist/api/index.mjs:238:52)
This is my first time doing something like this and not sure what the proper way to do it is. A few thoughts: - Why the heck is React called out when I am using SolidJS? Feels like IDEs assume React too much šŸ˜† - Is this the way I should be doing things? Am I allowed to have the convenience of using a component here? - If it is possible, what do I need to be aware of when it comes to bundling the server now that I have a SolidJS component living there when I didn't have any before? Appreciate any input and insights here.
17 Replies
foolswisdom
foolswisdom•this hour
I don't have a lot of insight into this problem, but it's likely related to the issue that react JSX is a global namespace (while solid's must be imported). So they don't coexist in the same project very well This is definitely a problem that has come up for people. Try searching for global namespace or other descriptions of the problem in discord search (or github issues) There can also be issues with tooling like esbuild just assuming that all jsx is react (unrelated to namespacing)
Madaxen86
Madaxen86•22h ago
Maybe just add this to tsconfig
"jsx": "preserve",
"jsxImportSource": "solid-js",
"jsx": "preserve",
"jsxImportSource": "solid-js",
Not totally sure, but I think renderToString must be called on the server.
MaveriX89
MaveriX89OP•19h ago
@Madaxen86 yeah, I had all that already set in my typescript config since cI have a Solid SPA. All of the things I’m attempting is happening in my backend-for-frontend layer using Elysia. @foolswisdom yeah, it’s interesting. I’m using Vite to build my Solid SPA and using bun to build/run my server. Bun is configured to read my tsconfig.json and everything is set to point to Solid from a JSX standpoint.
foolswisdom
foolswisdom•19h ago
Before you added this layer, was bun processing the jsx? Wondering if this might be a general bun issue I for some reason thought that you added react to project. Could it be the elysia automatically installs it and is messing things up somehow?
MaveriX89
MaveriX89OP•19h ago
Nah, this whole problem started when I added a Solid component to my Elysia server layer because I’m in the process of adding email verification for Auth. My server is doing the work and I want to express the email’s HTML markup as a Solid component and then stringify the whole thing That’s a good question about whether something within Elysia brings React in somehow.. I even have my bunfig.toml JSX config set to Solid just for good measure and still the same outcome.
foolswisdom
foolswisdom•19h ago
Is there an equivalent of npm list? To see if there's react somewhere
MaveriX89
MaveriX89OP•19h ago
I assume there is. I’d be surprised if Bun doesn’t have that implemented yet. I’m using Bun for everything except for building/bundling the Frontend. I’ll give it a shot when I get back in front of my computer There’s a part of me that also has suspicions around how the file extensions are playing with each other (e.g. my importing of a TSX file within a normal TS file). Everything in my Elysia layer is TS except for that one component module.
Brendonovich
Brendonovich•18h ago
If bun is doing the TS transpiling then it'll need to know how to transform the JSX, TS might just be doing typechecking
MaveriX89
MaveriX89OP•17h ago
Yeah, Bun should be picking up what I have configured in my tsconfig for sure according to their docs. I also added a JSX pragma in the TSX module for good measure and set it to solid-js
Brendonovich
Brendonovich•17h ago
I don't think that's sufficient to actually perform the JSX transform, that requires the babel plugin
MaveriX89
MaveriX89OP•17h ago
Do I really need Babel though? Bun can natively process JS/TS and JSX/TSX out of the box. Unless there’s a dot that I’m missing in the whole mental model
Brendonovich
Brendonovich•17h ago
Since solid uses a custom JSX transform it's necessary to have the babel plugin run on it Bun only supports the React JSX transform
MaveriX89
MaveriX89OP•17h ago
Ah interesting. I thought they had some basic support since in the bunfig.toml I can set both jsx: preserve and jsxImportSource: ā€œsolidā€
Brendonovich
Brendonovich•17h ago
Nah Solid's compiler does all the work of JSX transformation, hence requiring jsx: preserve
MaveriX89
MaveriX89OP•17h ago
So now the question becomes how to add the babel transform into Bun’s toolchain. I haven’t done that myself yet. I’ll be in front of a computer soon to try things out
foolswisdom
foolswisdom•16h ago
I had assumed Babel was already in the mix since there is already a solid SPA... I guess it's being used via the vite plugin, so it's not obvious to users
Brendonovich
Brendonovich•15h ago
I think this is a separate app to the spa

Did you find this page helpful?