A full-stack company website and CMS for DS General PLC, built with modern TypeScript tooling. It includes a public marketing site, an admin dashboard, blog/careers modules, and content management workflows.
- React 19 with TanStack Router for type-safe file-based routing
- TailwindCSS + shadcn/ui for beautiful, accessible UI components
- Framer Motion for smooth animations
- React Query for server state management
- Lexical rich text editor for content creation
- Hono - Fast, lightweight server framework
- Drizzle ORM - Type-safe database operations
- PostgreSQL - Reliable database engine
- Better Auth - Flexible authentication (email/password + OAuth)
- Modular architecture - Easy to extend and maintain
- Full CMS dashboard for managing all content
- Blog system with rich text, tags, and SEO metadata
- Services and case studies showcase
- Careers portal with job listings
- Contact form with message management
- Partners and testimonials management
- Gallery and media management
- TypeScript throughout the entire stack
- Turborepo for optimized monorepo builds
- Bun as the runtime and package manager
- ESLint + Prettier for consistent code style
- Husky for git hooks
The easiest way to get started is with the automated setup script:
# Clone the repository
git clone https://github.com/NegusNati/DS-General-website.git
cd DS-General-website
# Run the setup script
bun setupThe bun setup script will automatically:
- Check that prerequisites are installed (Bun, Docker)
- Install all workspace dependencies
- Create
.envfrom.env.exampleat the project root - Create
.env.prodfrom.env.prod.exampleat the project root (if missing) - Start PostgreSQL database via Docker Compose
- Push the database schema using Drizzle ORM
- Seed the database with sample content
Once setup completes, start the development servers:
bun devThe web app runs on http://localhost:5173 and the API on http://localhost:3000.
If you prefer to set things up manually or need more control:
# Clone the repository
git clone https://github.com/NegusNati/DS-General-website.git
cd DS-General-website
# Install dependencies
bun install
# Set up environment variables at root
cp .env.example .env
# Edit .env with your configuration
cp .env.prod.example .env.prod
# Edit .env.prod for local production-style runs only
# Start the database (if using Docker)
bun db:start
# Push the schema to the database
bun db:push
# (Optional) Seed with sample data
bun db:seed
# Start development servers
bun devDS-General-website/
├── apps/
│ ├── web/ # React frontend
│ │ ├── src/
│ │ │ ├── routes/ # File-based routes
│ │ │ ├── features/ # Feature components
│ │ │ ├── components/ # Shared UI components
│ │ │ ├── lib/ # API clients and utilities
│ │ │ └── config/ # Template configuration
│ │ └── public/ # Static assets
│ └── server/ # Hono API server
│ ├── src/
│ │ ├── modules/ # Feature modules (blogs, services, etc.)
│ │ ├── core/ # HTTP infrastructure
│ │ └── shared/ # Cross-cutting utilities
│ └── scripts/ # CLI tools
├── packages/
│ ├── db/ # Database schema and migrations
│ ├── auth/ # Authentication configuration
│ └── types/ # Shared TypeScript types
└── docs/ # Documentation
Brand/SEO defaults are centralized through:
packages/types/src/brand-seo.ts(shared contract + defaults)apps/web/src/lib/brand-seo-config.ts(web adapter with env overrides)apps/server/src/shared/branding/brand-seo-config.ts(server adapter with env overrides)
Override precedence is:
- shared defaults
- template defaults (
apps/web/src/config/template.ts) for web - environment variables (
.env)
Environment variables are centralized at the repository root:
.envfor local development.env.prodfor local production execution.env.example/.env.prod.exampleas tracked templates
See .env.example for all available options:
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
BETTER_AUTH_SECRET |
Authentication secret (min 32 chars) |
BETTER_AUTH_URL |
API server URL for auth callbacks |
CORS_ORIGIN |
Comma-separated allowed origins |
VITE_SERVER_URL |
API URL for frontend requests |
VITE_SITE_URL |
Frontend URL for SEO/OG tags |
SITE_URL |
Canonical frontend URL for server SSR |
SITE_TITLE |
Default SEO title (server-side) |
SITE_DESCRIPTION |
Default SEO description (server-side) |
TWITTER_HANDLE |
Twitter/X handle for cards |
GOOGLE_CLIENT_ID |
Google OAuth client ID (optional) |
GOOGLE_CLIENT_SECRET |
Google OAuth client secret (optional) |
The server, auth package, database tooling, and web scripts load from root env files only.
For production Docker runs, use the production env file explicitly:
docker compose --env-file .env.prod -f docker-compose.prod.yml up -dFor the DS General VPS deployment, keep the real production env file only on the server at /opt/ds-general/.env. Do not commit it to Git. See docs/deploy_ds.md for the full rollout steps.
| Command | Description |
|---|---|
bun setup |
Automated project setup (recommended) |
bun dev |
Start all apps in development mode |
bun build |
Build all apps for production |
bun lint |
Run ESLint |
bun format |
Format code with Prettier |
bun check-types |
TypeScript type checking |
bun db:push |
Push schema changes to database |
bun db:studio |
Open Drizzle Studio |
bun db:seed |
Seed database with sample data |
bun db:start |
Start Docker PostgreSQL |
bun db:stop |
Stop Docker PostgreSQL |
Use the module generator:
cd apps/server
bun run scripts/new-module.ts your-module-nameThis creates a complete module with:
- Repository (data access)
- Service (business logic)
- Controller (HTTP handlers)
- Routes (endpoint definitions)
- Validators (Zod schemas)
| Route | Description |
|---|---|
/ |
Marketing site home |
/dashboard/* |
CMS admin dashboard |
/login, /register |
Authentication |
See CONTRIBUTING.md for guidelines.
See SECURITY.md for security policy and reporting vulnerabilities.
MIT License - see LICENSE for details.
Built with Better-T-Stack and inspired by modern full-stack TypeScript best practices.