Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CI Pipeline

on:
push:
branches:
- main
- dev
pull_request:
branches:
- main
- dev

jobs:
validate:
name: Build, Lint, and Test
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Check Formatting
run: npx prettier --check .

- name: Run Linter
run: npm run lint

- name: Check Types
run: npm run typecheck

- name: Run Vitest
run: npm run test

- name: Verify Build
run: npm run build
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
node_modules/
dist/
.env
.DS_Store
*.log
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
10 changes: 10 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"tabWidth": 2,
"useTabs": true,
"printWidth": 80,
"bracketSpacing": true,
"arrowParens": "always"
}
118 changes: 68 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,68 @@
# [SYSTEM PROMPT] Clock Website Development Assistant

## 1. AI Directives

**Persona:** You are an expert pair programmer specializing in modern frontend development.

**Mission:** Your objective is to assist in developing this portfolio project by writing clean, high-quality code. Analyze the provided context thoroughly before generating solutions.

**Rules of Engagement:**

- **Primary Language:** Use **TypeScript** for all new application logic (`.ts` files). Use HTML and CSS for structure and styling as needed.
- **Style:** Prioritize clarity and simplicity. Adhere to the existing code style.
- **Commits:** All Git commit messages you generate must follow the Conventional Commits specification (e.g., `feat:`, `fix:`, `chore:`).
- **Output:** Provide responses as complete code files, diffs, or executable shell commands.

---

## 2. Project Architecture & Codebase Context

### **Technology Stack:**

- **TypeScript**: Handles all clock logic and DOM manipulation.
- **Vite**: Serves as the build tool and local dev server.
- **Vercel**: Manages automated hosting and CI/CD.

### **Core File Analysis:**

- **`src/index.html`**:

- Contains the basic structure for the application.
- Key elements include a `<div id="clock-container">` which holds the `#clock` and `#timezone` displays, and an `#environment-marker`.
- It loads `script.ts` as a module.

- **`src/script.ts`**:

- This is the main entry point for the application's logic.
- The `updateClock()` function is the core of the application. It runs every second via `setInterval`.
- **Logic Summary**: It fetches the current time, converts 24-hour time to 12-hour format with AM/PM, and displays it in the `#clock` element. It also detects and displays the user's local time zone in the `#timezone` element.
- It includes logic to display a "DEV" marker when running in a Vite development environment (`import.meta.env.MODE === 'development'`).

- **`src/style.css`**:
- Implements a dark, centered, "digital clock" aesthetic.
- Uses Flexbox to center the clock vertically and horizontally.
- Includes a basic media query to improve readability on smaller screens.

---

## 3. Development Task List

_(Please populate this section with your desired tasks.)_
# Simple Clock

A clean, dark-themed digital clock with a built-in countdown timer. Built with TypeScript and Vite.

## Tech Stack

- **TypeScript** — Application logic and DOM manipulation
- **Vite** — Build tool and dev server
- **Vitest** — Unit testing with jsdom

## Project Structure

```
src/
├── main.ts # Entry point (4 lines — thin glue)
├── index.html # HTML shell
├── vite-env.d.ts # Vite client types
├── assets/
│ └── favicon.svg
├── components/
│ ├── clock.ts # Clock UI — initClock(), pure computeClockTick()
│ └── timer.ts # Timer UI — initTimer(), thin renderer for timer-core
├── styles/
│ ├── main.css # Import hub
│ ├── variables.css # Design tokens
│ ├── base.css # Reset / body
│ ├── clock.css # Clock styles
│ ├── timer.css # Timer styles
│ ├── animations.css # Keyframes
│ └── responsive.css # Media queries
└── utils/
├── time.ts # Time formatting (pure functions)
├── audio.ts # Web Audio beep (injectable AudioContext)
├── timer-core.ts # Pure timer state machine (no DOM)
└── __tests__/
├── time.test.ts
├── clock.test.ts # (in components/__tests__/)
└── timer-core.test.ts
```

## Architecture

The codebase is structured for **testability**:

- **Pure functions** (`timer-core.ts`, `time.ts`, `computeClockTick`) contain all business logic with zero DOM dependencies — fully unit-testable.
- **UI layers** (`initClock`, `initTimer`) are thin wrappers that query the DOM, bind events, and render state from the pure core.
- **Dependency injection** — `playBeep()` accepts an optional `AudioContext`, enabling test mocking.

## Scripts

```bash
npm run dev # Start dev server (auto-opens browser)
npm run build # Production build → dist/
npm test # Run tests once
npm run test:watch # Run tests in watch mode
```

## Testing

```bash
npm test
```

Tests cover:

- Time formatting (12h, AM/PM, midnight, noon, duration)
- Clock tick logic (title updates, timezone display, dev marker, timer-active guard)
- Timer state machine (start/pause/reset/tick transitions, input validation, presets)
30 changes: 30 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
],
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/consistent-type-imports': [
'error',
{ prefer: 'type-imports' },
],
'no-console': ['warn', { allow: ['error', 'warn'] }],
},
},
{
ignores: ['dist/', 'node_modules/', 'eslint.config.js', 'vite.config.ts'],
},
);
6 changes: 0 additions & 6 deletions jest.config.cjs

This file was deleted.

Loading
Loading