| 1 | # @alchemy.run/frontend-frameworks/solidstart |
| 2 | |
| 3 | Adapter-free SolidStart integration: programmatic build and dev for SolidStart |
| 4 | projects, with the deploy platform passed in as a **deploy target** value. AWS |
| 5 | Lambda is the built-in target (`@alchemy.run/frontend-frameworks/solidstart/aws`); |
| 6 | the framework half of this package contains no AWS code at all. |
| 7 | |
| 8 | ## Architecture: framework half × target half |
| 9 | |
| 10 | | Module | Role | |
| 11 | | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 12 | | `@alchemy.run/frontend-frameworks/solidstart` (`SolidStart.ts`, `index.ts`, `UserConfig.ts`) | **Framework half.** Drives the PROJECT's own Vite install (`createBuilder(...).buildApp()` for build, `createServer()` for dev), appends the SolidStart nitro plugin carrying the target's preset, and maps nitro's `.output` onto framework-core's `BuildOutput`. Target-agnostic — zero AWS imports. | |
| 13 | | `@alchemy.run/frontend-frameworks/solidstart/aws` (`aws.ts`) | **Target half.** The AWS Lambda `SolidStartTarget`: nitro's `aws-lambda` preset, `awsLambda.streaming`, the Node bundle settings, and the wholesale `build` hook that runs the build in a disposable child process. | |
| 14 | |
| 15 | Background on why the integration is shaped this way: |
| 16 | |
| 17 | - **SolidStart 2 is expressed entirely as Vite plugins.** `solidStart()` from |
| 18 | `@solidjs/start/config` declares the `client` and `ssr` environments and a |
| 19 | `builder.buildApp` that builds both; `@solidjs/vite-plugin-nitro-2` declares |
| 20 | a second `buildApp` that additionally runs nitro over the emitted SSR |
| 21 | bundle. There is no adapter file and no framework CLI to drive. |
| 22 | - **`vite.build()` is not enough.** Vite's legacy `build()` builds one |
| 23 | environment, so it would silently produce the client bundle and no server. |
| 24 | The integration uses `createBuilder(...).buildApp()`, the path `vite build` |
| 25 | itself takes. |
| 26 | - **The deploy target owns the nitro preset, and the plugin is the only seam.** |
| 27 | `nitroV2Plugin` always passes a `preset` down to nitro (its own default is |
| 28 | `node-server`), so neither `NITRO_PRESET` nor a `nitro.config.ts` can |
| 29 | override it. The integration therefore constructs the plugin itself and |
| 30 | appends it through vite's inline config: inline plugins are concatenated |
| 31 | after the config file's, and vite merges plugin `config()` results in order, |
| 32 | so the appended instance's `buildApp` gets the last word. A project that |
| 33 | registers `nitroV2Plugin` in its own vite config would have its nitro |
| 34 | options silently dropped, so that **fails the build with an actionable |
| 35 | error** (`hasForeignNitroPlugin` / `pluginConflictMessage`) — nitro options |
| 36 | belong on the integration's `nitro` option, which forwards them. |
| 37 | - **The `aws-lambda` output needs no finishing pass.** Nitro emits |
| 38 | `.output/server/index.mjs` exporting a `handler`, its own |
| 39 | `package.json` (`type: "module"`), and copied externals under |
| 40 | `.output/server/node_modules` — a complete Node deployment unit. Client |
| 41 | assets and prerendered pages land in `.output/public`. |
| 42 | - **Builds run in a child process.** `solidStart()` scans the route directory |
| 43 | from `process.cwd()` at config-load time and user plugins may mutate the |
| 44 | process, so the AWS target's wholesale `build` spawns |
| 45 | `core/BuildChildRunner` with `cwd = <project root>`. |
| 46 | - **Dev aligns the cwd instead.** The dev server runs in the caller's process |
| 47 | (alchemy's dev sidecar), so `inProjectCwd` sets the cwd across the window in |
| 48 | which vite evaluates the config module and restores it immediately after. |
| 49 | Consequence, upstream and unavoidable while the plugin keys off the cwd: one |
| 50 | process hosts the dev server of one SolidStart project at a time. |
| 51 | - **No Cloudflare target.** Cloudflare deploys SolidStart through its native |
| 52 | Vite integration (`Cloudflare.Website.Vite`) with no nitro step at all. |