Project Structure
Understanding the organization and architecture of the Nuxt Aegis codebase.
Overview
Nuxt Aegis follows a modular architecture that separates client-side, server-side, and shared concerns. This page details the project structure, key components, and how they interact.
Repository Structure
nuxt-aegis/
├── src/ # Module source code
│ ├── module.ts # Module entry point & configuration
│ └── runtime/ # Runtime code (injected into Nuxt app)
│ ├── app/ # Client-side code
│ ├── server/ # Server-side code
│ ├── tasks/ # Background tasks
│ └── types/ # TypeScript type definitions
├── docs/ # VitePress documentation
├── playground/ # Development playground
├── examples/ # Example implementations
├── test/ # Test suites
└── specs/ # Requirements specificationsSource Structure (src/)
Module Entry (module.ts)
The main module definition that integrates with Nuxt.
typescript
// src/module.ts
export default defineNuxtModule({
meta: {
name: 'nuxt-aegis',
configKey: 'nuxtAegis',
},
setup(options, nuxt) {
// 1. Add runtime directory
addServerHandler()
addPlugin()
addComponent()
// 2. Configure storage
setupStorage()
// 3. Register server routes
registerAuthRoutes()
// 4. Add type declarations
addTypeTemplate()
// 5. Register background tasks
registerCleanupTasks()
},
})Key Responsibilities:
- Module configuration and options
- Runtime code injection
- Server route registration
- Storage configuration
- Type template generation
- Hook registration
Client-Side Structure (src/runtime/app/)
Plugins (plugins/)
app/plugins/
├── api.client.ts # Client API interceptors
├── api.server.ts # Server API handling (SSR)
└── ssr-state.server.ts # SSR state hydrationComposables (composables/)
app/composables/
└── useAuth.ts # Main authentication composableuseAuth.ts - Primary authentication API
typescript
export function useAuth() {
return {
// State
isAuthenticated: computed(() => ...),
user: computed(() => ...),
isLoading: ref(false),
// Methods
login: (provider: string) => ...,
logout: () => ...,
refresh: () => ...,
}
}Middleware (middleware/)
app/middleware/
├── auth-logged-in.ts # Require authenticated user
└── auth-logged-out.ts # Require logged-out userauth-logged-in.ts - Route protection for authenticated routes
typescript
export default defineNuxtRouteMiddleware((to, from) => {
const { isAuthenticated } = useAuth()
if (!isAuthenticated.value) {
return navigateTo('/login')
}
})Server-Side Structure (src/runtime/server/)
Routes (routes/)
server/routes/
└── auth/
├── token.post.ts # Exchange auth CODE for JWT
├── refresh.post.ts # Refresh JWT token
├── logout.post.ts # Logout and revoke tokens
├── [provider].get.ts # OAuth initiation
└── password/
├── register.post.ts # User registration
├── register-verify.get.ts # Email verification
├── login.post.ts # User login
├── login-verify.get.ts # Email verification
├── reset.post.ts # Password reset request
├── reset-verify.get.ts # Password reset verification
├── reset-confirm.post.ts # Confirm new password
└── change.post.ts # Change password (authenticated)Providers (providers/)
server/providers/
├── google.ts # Google OAuth provider
├── github.ts # GitHub OAuth provider
├── auth0.ts # Auth0 provider
├── password.ts # Password authentication
├── mock.ts # Mock provider (testing)
└── oauthBase.ts # Base provider interfaceOAuth Provider Implementation Structure:
typescript
// OAuth providers use a declarative implementation pattern
const providerImplementation = defineOAuthProvider({
runtimeConfigKey: 'google', // Provider identifier
defaultConfig: { scopes: ['openid', 'profile', 'email'] },
authorizeUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
tokenUrl: 'https://oauth2.googleapis.com/token',
userInfoUrl: 'https://www.googleapis.com/oauth2/v3/userinfo',
// Extract user info from provider response
extractUser: (userResponse) => userResponse,
// Build authorization URL query parameters
buildAuthQuery: (config, redirectUri, state) => ({
response_type: 'code',
client_id: config.clientId,
redirect_uri: redirectUri,
scope: config.scopes.join(' '),
state,
}),
// Build token exchange body parameters
buildTokenBody: (config, code, redirectUri) => ({
code,
client_id: config.clientId,
client_secret: config.clientSecret,
redirect_uri: redirectUri,
grant_type: 'authorization_code',
}),
})
// Create event handler using the implementation
export function defineOAuthGoogleEventHandler(options) {
return defineOAuthEventHandler(providerImplementation, options)
}Middleware (middleware/)
server/middleware/
└── auth.ts # Server route protectionPlugins (plugins/)
server/plugins/
└── ssr-auth.ts # SSR authentication statessr-auth.ts - Inject auth state into SSR context
typescript
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('render:response', async (response, { event }) => {
// Get auth state from refresh token
const refreshToken = getCookie(event, 'aegis_refresh')
if (refreshToken) {
const user = await getRefreshTokenUser(refreshToken)
if (user) {
// Inject into SSR state
response.ssrContext.payload.aegisAuth = {
isAuthenticated: true,
user: user,
}
}
}
})
})Background Tasks (src/runtime/tasks/)
tasks/
└── cleanup/
├── refresh-tokens.ts # Clean expired refresh tokens
├── magic-codes.ts # Clean expired magic CODEs
└── reset-sessions.ts # Clean expired reset sessionsNext Steps
- Authentication Flow - Complete authentication process
- Token Lifecycle - Token management details