Project Structure
VEF works best when projects are organized around page scenarios rather than around large shared buckets such as components, hooks, or services.
The sample application playground follows this structure and can be used as a reference.
This page explains the standard directory map. The mandatory naming rules, placement rules, and forbidden patterns are defined in Application Project Conventions.
Recommended Layout
src/
api/
index.ts
request.ts
apis/
auth/
sys/
md/
pmr/
helpers/
config.ts
hooks/
use-upload/
pages/
__root.tsx
_common/
login.tsx
access-denied.tsx
_layout/
route.ts
index/
route.tsx
auth/
sys/
md/
pmr/
router/
context.ts
router.gen.ts
main.ts
Directory Responsibilities
| Directory | Purpose | Typical Contents |
|---|---|---|
api/ | Application-level API client setup | createApiClient(), request wrappers, shared headers |
apis/ | Domain API functions | findUserPage, createUser, refreshAuth |
helpers/ | App-level utilities unrelated to one domain | config readers, environment wrappers |
hooks/ | Reusable page hooks | uploads, modal state, composed behaviors |
pages/ | Route entries and page implementations | route.tsx, page components, local helpers |
router/ | Router instance and router context | createRouter(), RouterContext |
Typical Page Directory Split
A typical CRUD page is usually split like this:
pages/_layout/auth/user/
route.tsx
helpers/
index.ts
components/
basic-search.tsx
form.tsx
This keeps responsibilities clear:
route.tsxonly assemblesCrudPagecomponents/form.tsxonly renders form fieldscomponents/basic-search.tsxonly renders the search areahelpers/index.tsonly provides page-local type helpers such ascreateCrudKit()
API Directory Split
Splitting apis/ by domain usually works well:
apis/
auth/
auth.ts
user.ts
role.ts
menu.ts
sys/
app.ts
audit-log.ts
md/
department.ts
staff.ts
Each file typically does two things:
- Define interface types
- Export
createQueryFn()/createMutationFn()results
Basic Bootstrap Files
When starting a project from scratch, these files are usually created first:
src/main.tssrc/api/index.tssrc/router/context.tssrc/router/index.tssrc/pages/__root.tsxsrc/pages/_layout/route.tssrc/pages/_common/login.tsxsrc/pages/_common/access-denied.tsx