Structure Devflare projects around one authored config, explicit runtime files, and package-local deploy ownership
This is the practical answer to “what does a real Devflare project look like on disk?” — from a small worker package, to a multi-surface app, to a hosted SvelteKit package, to a Bun monorepo with several deployable workers.
Devflare projects stay readable when the package boundary is obvious, the authored files stay separate from generated output, and each runtime surface owns its own file. This page maps the common file types, then shows a few real project shapes from this repository so you can set up your package deliberately instead of accumulating conventions by accident.
- Best for
- Teams deciding how to lay out a new Devflare package or a multi-package workspace before file structure gets noisy
- Primary authored file
- in each deployable package
- Generated files
- , , and
- Monorepo rule
- Validate from the root, but deploy from the package that owns the config
Start with authored files, and treat generated files as output
The first architecture decision is not “which framework?” It is usually “which files in this package are actually authored source of truth?” In Devflare, the stable answer is that , , and your runtime files are authored; generated Wrangler-facing files and generated types are downstream outputs.
That split is what keeps the project reviewable. If a file describes package intent or runtime behavior, author it directly. If a file is emitted by Devflare, a framework adapter, or Wrangler preparation, treat it as disposable output and regenerate it when the source changes.
| Path or pattern | Own it when | What it means |
|---|---|---|
| Every deployable package | The authored Devflare source of truth for files, bindings, env overlays, previews, and deployment posture. | |
| Every package | Package-local scripts, dependencies, and the command loop that should run from that package. | |
| The package owns request-wide HTTP behavior | The main worker entry for broad middleware or request handling. | |
| The package uses file-based HTTP leaves | URL-specific route handlers that sit beside, or replace, one large fetch file. | |
| , , | The package consumes those platform events | Separate event surfaces instead of burying background logic inside fetch code. |
| The package owns Durable Object classes | Stateful classes discovered and bundled through config. | |
| The package exposes named worker entrypoints | Classes discovered for typed service boundaries. | |
| The package owns workflow definitions | Additional discovered runtime modules that stay explicit in config review. | |
| Local RPC-style bridge calls must preserve custom values | Custom encode/decode rules for local bridge-backed calls, most often in tests or Durable Object method round-trips. | |
| You run | Generated binding and entrypoint types. Do not hand-edit it. | |
| , , | The package is a hosted Vite or SvelteKit app | Host-app files that sit around the Devflare worker story instead of replacing it. |
| , | Devflare has built, checked, or prepared deploy output | Generated build and deploy artifacts. Useful to inspect, not the authored architecture. |
A good architecture rule
If the file describes package intent, author it. If the file exists because Devflare or a host tool generated it, inspect it when needed but keep the authored source elsewhere.
A worker-first package can stay small for a long time
A healthy Devflare package can start with one config file, one , one route tree, and one small test. That already gives you package-local scripts, generated types, generated deploy output, and room to grow without forcing a framework or a monorepo strategy on day one.
The point of this shape is not minimalism for its own sake. It is that the package boundary stays obvious: the package owns its config, owns its worker files, and can be built or deployed without pretending the whole repo is one worker.
- Keep the package-local command loop in so , , , and always resolve the right config.
- Keep request-wide and let own the URL-specific work once there is more than one leaf.
- Expect , , and to appear as generated outputs after the normal command loop runs.
Small worker package with one config, one fetch file, one route tree, and generated output kept in its lane
One package can own many runtime files without becoming a monolith
This is where Devflare architecture becomes more interesting than “one fetch file.” A single package can still own HTTP, route modules, queue work, scheduled jobs, email handlers, Durable Objects, named entrypoints, workflows, and transport rules — as long as each surface keeps its own file and the config names those surfaces explicitly.
The lane matters for this reason. It is the map of which runtime surfaces the package actually owns.
| File lane | Why it exists |
|---|---|
| Request-wide middleware and the outer HTTP trail. | |
| Leaf handlers that mirror URLs instead of bloating the global fetch file. | |
| , , | Background and platform-triggered event surfaces with their own runtime contracts. |
| Stateful Durable Object classes discovered and bundled through config. | |
| Named worker entrypoints for typed cross-worker boundaries. | |
| Workflow definitions discovered as part of the package runtime shape. | |
| Local bridge serialization only when custom values need to survive a bridge-backed call. |
Not every package should own every file type
The point is explicit ownership, not maximal surface area. Add each runtime file only when the package really owns that event or discovery lane.
A single package with all the main worker-owned file types visible on disk
Hosted apps add Vite or SvelteKit around the worker, not instead of it
The docs app in this repo is the simplest real example of a hosted package: it has , , , , Svelte route files, and static assets. Devflare still owns the Cloudflare-facing config and generated Wrangler output, while Vite and SvelteKit own the host-app shell.
The repo also includes a fuller SvelteKit case that points at the generated Cloudflare worker output while still discovering Durable Objects and transport hooks from source. That is the important hosted-app lesson: the framework shell and the worker surfaces can coexist in one package when the file ownership stays explicit.
- Package-local host files like and belong beside the Devflare config, not in a separate orchestration package.
- Hosted apps can point at generated framework worker output, or they can mix that output with extra Devflare-owned surfaces like Durable Objects and transport hooks.
- The generated worker file still belongs on the generated side of the boundary; the authored source remains the config plus the source files that feed it.
Real hosted app package from `apps/documentation`
Hosted SvelteKit package that still owns extra worker surfaces
In a monorepo, Turbo orchestrates the workspace but packages still deploy themselves
This repository is the monorepo example. The root owns workspace scripts, workspaces, and Turbo task orchestration. But deployable packages still keep their own files and package-local commands. That is true for , , sidecar workers under , and the smaller cases under .
That split is what keeps the monorepo honest. Root scripts decide what to validate or cache. Package-local Devflare commands decide what actually resolves, builds, deploys, or cleans up.
- 1
Use the repo root for Turbo build, test, check, and impacted-package orchestration.
- 2
Run from the package that owns the config you actually mean to resolve.
- 3
Keep sidecar workers or service-bound packages as separate workspace packages with their own configs and scripts.
- 4
Reuse one preview scope across a worker family only after you have made the package boundaries explicit.
Turbo is not the deploy target
Turbo decides which packages need work. The package working directory still decides which gets built or deployed.
The repo root orchestrates, but the packages still own deployment
Good monorepo command split
Open the deeper page for the part of the architecture you are deciding next
Configuration
Need the file-surface rules?
Open project shape when the next question is how many surfaces the package should actually own and which conventions should stay explicit.
Configuration
Need the event-surface map?
Open worker surfaces when the real question is fetch versus queue versus scheduled versus email, or when the package has started owning more than one event family.
Routing
Need route layout next?
Open the routing page when the package boundary is clear and the next decision is how and should split responsibility.
Configuration
Need generated types and entrypoints?
Open generated types when the architecture includes bindings, named entrypoints, service refs, or Durable Objects that should land in accurately.
Ship & operate
Need the fuller monorepo workflow?
Open the monorepo page when the next question is Turbo filters, CI workflow boundaries, or package-local deploy discipline across the workspace.
Previous
CLI
Start at : the root page already maps local dev, inspection, deploy intent, account inventory, preview lifecycle, production control, token management, AI pricing, and remote-mode operations in one place.
Next
Bridge internals
The bridge architecture document remains valuable, but it should not be on the first-hour developer path.