Welcome to
Skip to main content
Home/Documentation/Development Setup

Development Setup

Prerequisites, installation, and local development workflow

Prerequisites

Before you begin, ensure you have the following installed:

ToolVersionInstall
Node.js≥ 22.5.0nodejs.org
pnpm10.26.xpnpm.io/installation
CorepackBuilt-inShips with Node.js 16+
GitLatestgit-scm.com

Enable Corepack

Corepack manages the correct pnpm version automatically:

corepack enable

Verify Installation

node -v    # Should output v22.x.x or higher
pnpm -v    # Should output 10.26.x

Installation

1. Clone the Repository

git clone https://github.com/INOV-NORTE/hub-digital-ui.git
cd hub-digital-ui

2. Install Dependencies

pnpm install

This installs dependencies for all workspace packages (apps, packages, tooling).

3. Configure Environment

cp .env.sample .env

Edit .env with your configuration. At minimum, you need:

# Site URL
NUXT_PUBLIC_SITE_URL="http://localhost:3000"

# Directus API (required)
DIRECTUS_URL="https://api.hub.inov-norte.ipp.pt"

# Disable coming-soon for local development
NUXT_PUBLIC_COMING_SOON_ENABLED=false

4. Start Development Server

pnpm dev

The app will be available at http://localhost:3000.

Turborepo orchestrates all workspace packages. The pnpm dev command from the root runs nuxt dev for the web app with the correct environment variables.


Development Workflow

File-Based Routing

Pages are automatically generated from the pages/ directory. For example:

FileRoute
pages/index.vue/
pages/auth/login.vue/auth/login
pages/catalog/courses/index.vue/catalog/courses
pages/dashboard/index.vue/dashboard
pages/docs/[...path].vue/docs/*
pages/profile/[id].vue/profile/:id

Auto-Imports

Components and composables from modules/ directories are auto-imported. You don't need to write:

// ❌ Don't do this
import { useAuthStore } from '~/stores/auth';
import Button from '~/modules/ui/components/button/Button.vue';

Instead, just use them directly:

// ✅ Just use them
const authStore = useAuthStore();
<!-- ✅ Components are globally available -->
<Button variant="primary">Click me</Button>

Adding shadcn-vue Components

To add a new UI component from shadcn-vue:

cd apps/web
pnpm shadcn-vue add <component-name>

For example:

pnpm shadcn-vue add slider
pnpm shadcn-vue add switch

Components are installed to modules/ui/components/<component-name>/.

Creating a New Module

  1. Create the module directory:
mkdir -p modules/<module-name>/{components,composables}
  1. Register it in nuxt.config.ts:
// In imports.dirs (for composables)
imports: {
  dirs: [
    // ...existing
    "modules/<module-name>/composables/**",
  ],
},

// In components (for Vue components)
components: [
  // ...existing
  { path: "@/modules/<module-name>/components", pathPrefix: false },
],

Adding Translations

  1. Edit translation files in packages/i18n/translations/:
    • en.json — English
    • pt.json — Portuguese
  2. Use translations in components:
<template>
  <p>{{ $t('my.translation.key') }}</p>
</template>

<script setup>
const { t } = useI18n();
const message = t('my.translation.key');
</script>

Pinia Stores

State is managed with Pinia stores in stores/:

// stores/myFeature.ts
export const useMyFeatureStore = defineStore('myFeature', {
  state: () => ({
    items: [],
    loading: false,
  }),
  actions: {
    async fetchItems() {
      const { $directus } = useNuxtApp();
      this.loading = true;
      try {
        this.items = await $directus.request(readItems('my_collection'));
      } finally {
        this.loading = false;
      }
    },
  },
});

Common Tasks

Running the Build Locally

pnpm build

If you encounter memory issues:

NODE_OPTIONS="--max-old-space-size=8192" pnpm build

Linting

pnpm lint        # Check for lint errors
pnpm lint:fix    # Auto-fix lint errors

Formatting

pnpm format      # Format with Prettier

Type Checking

cd apps/web
pnpm typecheck

E2E Testing

cd apps/web
pnpm e2e

This starts the dev server and launches Cypress.


Troubleshooting

ECONNRESET or UND_ERR_HEADERS_TIMEOUT

These errors indicate network issues between the Nuxt server and the Directus backend. Verify:

  1. DIRECTUS_URL is reachable from your machine
  2. No VPN or firewall is blocking the connection
  3. The Directus server is running and responding

JavaScript heap out of memory

Increase Node.js memory limit:

NODE_OPTIONS="--max-old-space-size=8192" pnpm dev

Hot Module Replacement (HMR) issues

If HMR stops working:

  1. Stop the dev server
  2. Clear the Nuxt cache: rm -rf apps/web/.nuxt
  3. Restart: pnpm dev

Port 3000 already in use

Find and kill the process:

lsof -i :3000
kill -9 <PID>