Prerequisites
Before you begin, ensure you have the following installed:
| Tool | Version | Install |
|---|---|---|
| Node.js | ≥ 22.5.0 | nodejs.org |
| pnpm | 10.26.x | pnpm.io/installation |
| Corepack | Built-in | Ships with Node.js 16+ |
| Git | Latest | git-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 devcommand from the root runsnuxt devfor the web app with the correct environment variables.
Development Workflow
File-Based Routing
Pages are automatically generated from the pages/ directory. For example:
| File | Route |
|---|---|
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
- Create the module directory:
mkdir -p modules/<module-name>/{components,composables}
- 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
- Edit translation files in
packages/i18n/translations/:en.json— Englishpt.json— Portuguese
- 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:
DIRECTUS_URLis reachable from your machine- No VPN or firewall is blocking the connection
- 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:
- Stop the dev server
- Clear the Nuxt cache:
rm -rf apps/web/.nuxt - Restart:
pnpm dev
Port 3000 already in use
Find and kill the process:
lsof -i :3000
kill -9 <PID>