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
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.3.1] - 2026-02-24

### Added

- Generator: Development Stages section (all specs) — progressive three-stage pattern: Local (mock), Integration (real API), Polish (optional)
- Generator: Mock Data templates (external-data specs) — context-aware structure guides (weather: location/temp, stock: ticker/price, news: title/date)
- Generator: Local Development Checklist (data-dependent specs) — pre-flight validation before wiring real APIs
- 11 new tests covering all three new sections and edge cases (139 total)

### Changed

- Generator: WiringGuide now includes mock data templates for API-based apps
- Generator: Pre-Ship Checklist now emphasizes building locally first before external integrations
- Service worker: bumped cache version to gist-v8

### Why

Specs now explicitly guide AI assistants to build locally-testable apps (mock-first, integrate-later). Solves "hard localhost dependencies" problem: developers can run `npm run dev` and see the app working immediately, without requiring external API setup upfront.

## [1.3.0] - 2026-02-24

### Added
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "gistapp",
"type": "module",
"version": "1.3.0",
"version": "1.3.1",
"private": true,
"engines": {
"node": ">=22"
Expand Down
2 changes: 1 addition & 1 deletion public/sw.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Gist service worker — offline-first static site caching
const CACHE_VERSION = 'gist-v7';
const CACHE_VERSION = 'gist-v8';
const PRECACHE_URLS = [
'/',
'/create/',
Expand Down
156 changes: 156 additions & 0 deletions src/lib/generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,162 @@ describe('generateSpec', () => {
const spec = generateSpec(minimalAnswers);
expect(spec).not.toContain('your AI assistant will handle the technical details');
});

// --- Part 1: Generator Observation Fixes ---

// Issue 1: Analytics "Worker endpoint" text scoping
it('standard tier without Worker: omits Worker endpoint text', () => {
const spec = generateSpec(userContentSavesDataAnswers);
expect(spec).toContain('Analytics');
expect(spec).not.toContain('Worker endpoint');
expect(spec).toContain('lightweight analytics service');
});

// Issue 2: Loading/Offline UX States guards
it('display-only user-content: omits Loading and Offline states', () => {
const spec = generateSpec({
...minimalAnswers,
dataSource: 'user-content',
userInputType: 'display-only',
});
expect(spec).not.toContain('**Loading**');
expect(spec).not.toContain('**Offline**');
});

it('external-data app: includes Loading and Offline states', () => {
const spec = generateSpec(standardAnswers);
expect(spec).toContain('**Loading**');
expect(spec).toContain('**Offline**');
});

it('static minimal-tier app: omits Loading and Offline', () => {
const spec = generateSpec(minimalAnswers);
expect(spec).not.toContain('**Loading**');
expect(spec).not.toContain('**Offline**');
});

// Issue 3: Context-aware Empty state prompts
it('weather API: generates location-specific prompt', () => {
const spec = generateSpec({
...standardAnswers,
apiDescription: 'Current weather and forecast for a location',
});
expect(spec).toContain('Prompt user for location');
expect(spec).toContain('**Empty / First Use**');
});

it('stock tracker API: generates ticker-specific prompt', () => {
const spec = generateSpec({
...standardAnswers,
apiDescription: 'Stock prices and market data',
});
expect(spec).toContain('ticker symbol');
});

it('news feed API: generates topic-specific prompt', () => {
const spec = generateSpec({
...standardAnswers,
apiDescription: 'News articles from various sources',
});
expect(spec).toContain('feed');
expect(spec).toContain('topics');
});

it('unknown external-data app: uses generic prompt', () => {
const spec = generateSpec({
...standardAnswers,
apiDescription: 'Some unknown data source',
apiKnownName: 'CustomAPI',
});
expect(spec).toContain('initial input');
expect(spec).not.toContain('location');
expect(spec).not.toContain('ticker');
});

// --- Localhost-first development improvements ---

it('all specs include Development Stages section', () => {
const minimalSpec = generateSpec(minimalAnswers);
const standardSpec = generateSpec(standardAnswers);
expect(minimalSpec).toContain('## Development Stages');
expect(standardSpec).toContain('## Development Stages');
});

it('Development Stages shows Stage 1 (Local) for all specs', () => {
const spec = generateSpec(minimalAnswers);
expect(spec).toContain('### Stage 1: Local (Mock Data)');
expect(spec).toContain('app works immediately on localhost');
});

it('Development Stages shows Stage 2 (Integration) only for specs with data dependencies', () => {
const minimalSpec = generateSpec(minimalAnswers);
const externalDataSpec = generateSpec(standardAnswers);
expect(minimalSpec).not.toContain('### Stage 2: Integration');
expect(externalDataSpec).toContain('### Stage 2: Integration');
});

it('Development Stages shows Stage 3 (Polish) for specs with data dependencies', () => {
const spec = generateSpec(standardAnswers);
expect(spec).toContain('### Stage 3: Polish');
});

it('weather API includes mock data template with location fields', () => {
const spec = generateSpec({
...standardAnswers,
apiDescription: 'Current weather and 7-day forecast for any location',
});
expect(spec).toContain('### Mock Data (for local development)');
expect(spec).toContain('location: string');
expect(spec).toContain('temp: number');
expect(spec).toContain('condition: string');
});

it('stock API includes mock data template with ticker fields', () => {
const spec = generateSpec({
...standardAnswers,
apiDescription: 'Real-time stock prices and market data',
});
expect(spec).toContain('### Mock Data (for local development)');
expect(spec).toContain('ticker: string');
expect(spec).toContain('price: number');
});

it('news API includes mock data template with article fields', () => {
const spec = generateSpec({
...standardAnswers,
apiDescription: 'Latest news articles and headlines',
});
expect(spec).toContain('### Mock Data (for local development)');
expect(spec).toContain('title: string');
expect(spec).toContain('description: string');
expect(spec).toContain('publishedAt: string');
});

it('external-data specs include Local Development Checklist', () => {
const spec = generateSpec(standardAnswers);
expect(spec).toContain('Before integrating external services');
expect(spec).toContain('App builds and runs locally with mock/fixture data');
expect(spec).toContain('All UX states testable with mock data');
});

it('specs without external data omit Local Development Checklist', () => {
const spec = generateSpec(minimalAnswers);
expect(spec).not.toContain('Before integrating external services');
});

it('user-saves-data specs include Local Development Checklist', () => {
const spec = generateSpec(userContentSavesDataAnswers);
expect(spec).toContain('Before integrating external services');
});

it('display-only user-content specs omit Local Development Checklist', () => {
const spec = generateSpec({
...minimalAnswers,
dataSource: 'user-content',
userInputType: 'display-only',
});
expect(spec).not.toContain('Before integrating external services');
});
});

describe('generateFilename', () => {
Expand Down
Loading