A modern full-stack TypeScript application built with Better-T-Stack.
Athens is a web application for the Athens client, designed as a phased proof of concept.
The initial focus is building a dashboard for viewing project updates about RAPTOR inspections. This phase prioritizes:
- Frontend Development β Building a polished, responsive UI with modern React patterns
- Simple Data Procedures β Minimal backend complexity to iterate quickly on the UI
- JSON-Based Data β Using local JSON files as the data source
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β Next.js β βββΊ β oRPC β βββΊ β Data β
β (Frontend) β β (Contracts) β β (JSON/DB) β
βββββββββββββββ βββββββββββββββ βββββββββββββββ
The data flow is designed with future flexibility in mind:
- Now: JSON files serve as the data source for rapid frontend development
- Later: FileMaker database connection via a custom OData client
We leverage oRPC's contract-first approach to predefine all inputs and outputs. This ensures:
- Consistent JSON structure regardless of the underlying data source
- Type-safe interfaces between frontend and backend
- Seamless migration from JSON files to FileMaker without frontend changes
- Clear API documentation via OpenAPI specs
The web application will always consume the same standardized JSON format, whether the data comes from static files or the FileMaker OData integration.
- Phase 2: FileMaker database integration via OData client
- Phase 3: Extended inspection features and reporting
- Phase 4: Full production deployment
- Next.js (App Router) - React framework with server-side rendering
- React 19 - Latest React with React Compiler support
- Tailwind CSS v4 - Utility-first CSS framework
- shadcn/ui - High-quality, accessible component library
- TanStack Query - Powerful data synchronization for React
- TanStack Form - Headless form library
- Next Themes - Dark mode support
- Sonner - Toast notifications
- oRPC - End-to-end type-safe RPC framework
- Type-safe APIs with automatic TypeScript inference
- OpenAPI integration for API documentation
- Zod validation built-in
- TanStack Query integration for seamless client-side hooks
- Better Auth - Modern authentication library
- Email/password authentication
- Session management
- Protected routes and API procedures
- TypeScript - Type safety across the entire stack
- Biome - Fast linter and formatter (replaces ESLint/Prettier)
- Turborepo - High-performance monorepo build system
- pnpm - Fast, disk space efficient package manager
- PWA Support - Progressive Web App capabilities with manifest and service worker ready
- React Compiler - Automatic React optimizations via Babel plugin
athens/
βββ apps/
β βββ web/ # Next.js frontend application
β βββ src/
β β βββ app/ # Next.js App Router pages
β β β βββ api/ # API routes
β β β β βββ auth/ # Better Auth API handler
β β β β βββ rpc/ # oRPC API route handler
β β β βββ dashboard/ # Protected dashboard page
β β β βββ login/ # Login/signup page
β β β βββ page.tsx # Home page
β β βββ components/ # React components
β β β βββ ui/ # shadcn/ui components
β β β βββ sign-in-form.tsx
β β β βββ sign-up-form.tsx
β β β βββ user-menu.tsx
β β βββ lib/ # Utility functions (auth client)
β β βββ utils/ # Client utilities (oRPC client setup)
β βββ public/ # Static assets
β
βββ packages/
β βββ api/ # Shared API package
β β βββ src/
β β βββ index.ts # oRPC setup & procedures
β β βββ context.ts # Request context creation
β β βββ routers/ # API route definitions
β β βββ index.ts # Main app router
β β
β βββ auth/ # Authentication package
β β βββ src/
β β βββ index.ts # Better Auth configuration
β β
β βββ config/ # Shared TypeScript configuration
β βββ tsconfig.base.json # Base TSConfig for all packages
β
βββ biome.json # Biome linter/formatter config
βββ turbo.json # Turborepo configuration
βββ pnpm-workspace.yaml # pnpm workspace configuration
The API package contains your business logic and type-safe procedures:
- Procedures: Define type-safe API endpoints using oRPC
- Context: Request context (includes auth session, database connections, etc.)
- Routers: Organize procedures into logical groups
- Protected Procedures: Use
protectedProcedurefor authenticated endpoints
Example procedures:
export const appRouter = {
// Public procedure
healthCheck: publicProcedure.handler(() => {
return "OK";
}),
// Protected procedure (requires authentication)
privateData: protectedProcedure.handler(({ context }) => {
return {
message: "This is private",
user: context.session?.user,
};
}),
};The Next.js app consumes the API through the oRPC client:
- API Route:
/api/rpc/[[...rest]]/route.tshandles all RPC requests - Auth Route:
/api/auth/[...all]/route.tshandles Better Auth requests - OpenAPI Docs: Available at
/api/rpc/api-reference - Client Setup:
src/utils/orpc.tsconfigures the oRPC client with TanStack Query - Usage: Use
orpc.procedureName.queryOptions()ororpc.procedureName.useQuery()in components - Pages: Home (
/), Login (/login), Dashboard (/dashboard- protected)
Better Auth is configured for email/password authentication:
- Configuration:
packages/auth/src/index.ts- Better Auth setup - Client:
apps/web/src/lib/auth-client.ts- Client-side auth utilities - Components: Sign-in and sign-up forms, user menu with session management
- Protected Routes: Dashboard page and protected API procedures
- Note: Database connection needs to be configured for full functionality
- Node.js 18+
- pnpm 9+
# Install dependencies
pnpm install# Start development server (runs on port 3001)
pnpm run devOpen http://localhost:3001 in your browser.
# Build all applications
pnpm run buildpnpm run dev- Start all applications in development modepnpm run build- Build all applications for productionpnpm run check-types- Type-check all TypeScript codepnpm run check- Run Biome linting and formatting (with auto-fix)pnpm run dev:web- Start only the web apppnpm run dev:native- Start only native app (if configured)
pnpm run dev- Start Next.js dev server (port 3001)pnpm run build- Build Next.js app for productionpnpm run start- Start production serverpnpm run generate-pwa-assets- Generate PWA assets
- Base config:
packages/config/tsconfig.base.json - Strict mode enabled with comprehensive type checking
- Path aliases configured (
@/forsrc/)
- Linting and formatting configured
- Auto-fix on save recommended
- Tailwind CSS class sorting enabled
- Caching enabled for faster builds
- Task dependencies configured
- Parallel execution where possible
- Define the procedure in
packages/api/src/routers/index.ts:
import { protectedProcedure, publicProcedure } from "../index";
import { z } from "zod";
export const appRouter = {
// Public procedure
healthCheck: publicProcedure.handler(() => {
return "OK";
}),
// Public procedure with input validation
getUser: publicProcedure
.input(z.object({ id: z.string() }))
.handler(async ({ input }) => {
// Your logic here
return { id: input.id, name: "User" };
}),
// Protected procedure (requires authentication)
getPrivateData: protectedProcedure.handler(({ context }) => {
// context.session.user is available here
return { userId: context.session.user.id };
}),
};- Use in components via the oRPC client:
import { orpc } from "@/utils/orpc";
import { useQuery } from "@tanstack/react-query";
// Public procedure
const { data, isLoading } = orpc.getUser.useQuery({ id: "123" });
// Or using queryOptions
const { data } = useQuery(orpc.getUser.queryOptions({ id: "123" }));
// Protected procedure (requires user to be authenticated)
const { data: privateData } = orpc.getPrivateData.useQuery();Once your dev server is running, visit:
- OpenAPI Documentation: http://localhost:3001/api/rpc/api-reference
The following oRPC procedures are available for the RAPTOR inspection dashboard:
| Procedure | Input | Description |
|---|---|---|
list |
{ region?, phase?, risk_level?, status?, limit?, offset? } |
List projects with optional filters |
getById |
{ id: string } |
Get single project by ID |
| Procedure | Input | Description |
|---|---|---|
list |
{ type?, location?, limit?, offset? } |
List assets with optional filters |
getById |
{ id: string } |
Get single asset by ID |
| Procedure | Input | Description |
|---|---|---|
list |
{ project_id?, asset_id?, limit?, offset? } |
List project-asset records |
getById |
{ id: string } |
Get single project-asset by ID |
getSummaryStats |
none | Dashboard topline stats (avg completion %) |
| Procedure | Input | Description |
|---|---|---|
list |
{ project_asset_id?, priority?, status?, system_group?, milestone_target?, limit?, offset? } |
List action items with filters |
getById |
{ id: string } |
Get single action item by ID |
getStatusSummary |
{ project_asset_id? } |
Counts by status and priority |
| Procedure | Input | Description |
|---|---|---|
getByProjectAsset |
{ project_asset_id: string } |
Latest summary for project asset |
getSystemProgress |
{ project_asset_id: string } |
Progress % per system group |
getActionItemCounts |
{ project_asset_id: string } |
Aggregated counts by priority |
import { orpc } from "@/utils/orpc";
// List all projects
const { data: projects } = orpc.projects.list.useQuery({ limit: 50 });
// Filter by region
const { data: northSeaProjects } = orpc.projects.list.useQuery({
region: "North Sea"
});
// Get dashboard stats
const { data: stats } = orpc.projectAssets.getSummaryStats.useQuery();
// Get action items for a project
const { data: actionItems } = orpc.smartList.list.useQuery({
project_asset_id: "1",
priority: "High",
status: "Open"
});pnpm test:apiTests verify FileMaker Data API connectivity and all CRUD operations.
This project uses shadcn/ui components. To add new components:
cd apps/web
pnpm dlx shadcn@latest add [component-name]Components are located in apps/web/src/components/ui/.
This is a pnpm workspace monorepo. Packages reference each other using workspace protocol:
@athens/api- The API package (oRPC procedures)@athens/auth- Authentication package (Better Auth configuration)@athens/config- Shared TypeScript config
Currently configured for:
- Frontend: Self-hosted (Next.js)
- Backend: Self-hosted (Next.js API routes)
- Database: None configured (required for authentication)
- Auth: Better Auth configured with email/password (database connection needed)
The app includes Better Auth for authentication:
- Sign In/Sign Up: Forms available at
/login - Protected Routes: Dashboard page requires authentication
- Session Management: User menu component shows current session
- API Protection: Use
protectedProcedurefor authenticated endpoints
To enable full authentication functionality, configure a database connection in packages/auth/src/index.ts.
- Next.js Documentation
- oRPC Documentation
- Better Auth Documentation
- TanStack Query Documentation
- Turborepo Documentation
- Biome Documentation
[Add your license here]