Skip to content

File Structure

Vla doesn’t enforce a specific file structure. You’re free to organize your code however you like. However, we recommend aligning your file structure with how Vla structures your code.

This page provides recommendations based on your app’s size and complexity.


Colocate Actions in your presentation layer (next to your UI components) in a separate file. Create a data.ts file for each group of files, which belong together. This file contains one or more Vla Actions, but no other layers (like Services, Repos or Resources).

  • Directorysrc/
    • Directoryapp/ Presentation Layer
      • Directoryposts/
        • data.ts
        • page.ts
        • Directory[slug]/
          • page.ts
      • Directoryauthors/
        • data.ts
        • page.ts
        • Directory[user]/
          • data.ts
          • page.ts
    • Directorycomponents/ Component Library
    • Directorydata/ Data Layer
      • users.ts
      • posts.ts
      • db.ts
      • kernel.ts

Think of each data.ts file like it defines a module boundary in your presentation layer:

  • Files inside a folder should only import from their closest data.ts.
  • Keep your components data-free, as a collection of reusable UI components which don’t fetch data from the data layer.
  • You can also choose a different file name, like actions.ts.

For example, using the file structure from above:

  • posts/page.ts and /posts/[slug]/page.ts would only import from posts/data.ts. They would not import from authors/.
  • authors/page.ts would only import from authors/data.ts, and not from posts/data.ts or authors/[users]/data.ts.
  • authors/[user]/page.ts would only import from authors/[user]/data.ts, and not from posts/data.ts or authors/data.ts.

For small apps or prototypes, keep it simple. A handful of files in a single folder is often enough.

  • Directorysrc/
    • Directoryapp/ Your framework’s routes
    • Directorydata/ Data Layer
      • users.ts Services and Repos
      • posts.ts Services and Repos
      • db.ts Resource
      • kernel.ts Kernel setup

To split model files into smaller files, you create a file for each layer and give them a suffix, like .service.ts and .repo.ts.

  • Directorysrc/
    • Directoryapp/
    • Directorydata/
      • Directoryresources/
        • db.ts
        • redis.ts
      • posts.repo.ts
      • posts.service.ts
      • users.repo.ts
      • users.service.ts

You can additionally group services and repos by their resource. This is especially helpful if you have multiple services for a model.

  • Directorysrc/
    • Directoryapp/
    • Directorydata/
      • Directoryresources/
        • db.ts
        • redis.ts
      • Directoryposts/
        • posts.repo.ts
        • posts.service.ts
      • Directoryusers/
        • users.repo.ts
        • users.service.ts
        • authors.service.ts

For large apps or teams, organize by modules to separate domains. Each module has its own directory with its own structure inside.

  • Directorysrc/
    • Directoryapp/
    • Directorydata/
      • kernel.ts
      • Directoryresources/
        • db.ts
        • redis.ts
      • Directoryusers/
        • user.facade.ts Public API for other modules
        • user.module.ts
        • user.repo.ts
        • user.service.ts
      • Directorybilling/
        • billing.facade.ts Public API for other modules
        • billing.module.ts
        • invoice.repo.ts
        • invoice.service.ts
        • subscription.repo.ts
        • subscription.service.ts
      • Directoryanalytics/
        • analytics.facade.ts Public API for other modules
        • analytics.module.ts
        • analytics.repo.ts
        • analytics.service.ts

As a module grows, you can further organize it internally.

Keep everything flat within the module directory.

  • Directorydata/
    • Directoryusers/
      • user.facade.ts
      • user.module.ts
      • user.repo.ts
      • user.service.ts

Group by model when the module has multiple models.

  • Directorydata/
    • Directorybilling/
      • billing.module.ts
      • billing.facade.ts
      • Directoryinvoice/
        • invoice.repo.ts
        • invoice.service.ts
      • Directorysubscription/
        • subscription.repo.ts
        • subscription.service.ts
      • Directorypayment/
        • payment.repo.ts
        • payment.service.ts

Resources like database clients are typically shared across modules, so keep them in a shared location.

  • Directorydata/
    • Directoryresources/
      • db.ts
      • redis.ts
      • s3.ts
    • Directoryusers/
    • Directorybilling/

You don’t need to choose the “perfect” structure upfront. Start simple and evolve:

  1. Start small - Single file or flat structure
  2. Split when needed - Break out files as they grow
  3. Group when clear - Add folders when grouping becomes obvious
  4. Modules when scaling - Introduce modules when domains become distinct