# Genui Workshop Step 6

> Execute Step 6 of the GenUI Workshop, creating the weather input widget and updating the system prompt.

- Skill: `flutter/genui-workshop-step-6` (Agent Skill)
- Install (CLI): `npx skillmds@latest add flutter/genui-workshop-step-6`
- Raw SKILL.md: https://api.skillmd.com/api/skills/flutter/genui-workshop-step-6/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: flutter (https://skillmd.com/u/flutter)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/flutter/genui-workshop-step-6

---


# GenUI Workshop - Step 6

**Goal**: Execute Step 6 of the GenUI workshop.

**Instructions**:
Use your code editing tools to create the weather input catalog widget and update the app's configuration.

1. Create `lib/catalog/weather_input.dart`:
```dart
import 'package:flutter/material.dart';
import 'package:genui/genui.dart';
import 'package:json_schema_builder/json_schema_builder.dart';

final simpleWeatherSchema = S.object(
  properties: {
    'location': S.string(description: 'The location to check the weather.'),
    'date': S.string(description: 'The date to check the weather.'),
  },
);

final weatherInput = CatalogItem(
  name: 'WeatherInput',
  dataSchema: simpleWeatherSchema,
  widgetBuilder: (itemContext) {
    final json = itemContext.data as Map<String, Object?>;
    final data = SimpleWeatherData.fromJson(json);
    return WeatherInput(
      data: data,
      onFetchRequest: (loc, date) async {
        final JsonMap resolvedContext = await resolveContext(
          itemContext.dataContext,
          {'location': loc, 'date': date.toString()},
        );
        itemContext.dispatchEvent(
          UserActionEvent(
            name: 'submit_weather_request',
            sourceComponentId: 'submitButton',
            timestamp: DateTime.now(),
            context: resolvedContext
          ),
        );
      },
    );
  },
);

class SimpleWeatherData {
  String location;
  DateTime date;

  SimpleWeatherData({required this.location, required this.date});

  factory SimpleWeatherData.defaultValues() {
    return SimpleWeatherData(location: 'Baltimore', date: DateTime.now());
  }

  factory SimpleWeatherData.fromJson(Map<String, Object?> json) {
    if (json.isNotEmpty) {
      return SimpleWeatherData(
        location: json['location'] as String,
        date: DateTime.parse(json['date'] as String),
      );
    } else {
      return SimpleWeatherData(location: 'Baltimore', date: DateTime.now());
    }
  }
}

class WeatherInput extends StatefulWidget {
  final SimpleWeatherData data;
  final void Function(String, DateTime) onFetchRequest;

  const WeatherInput({
    super.key,
    required this.data,
    required this.onFetchRequest,
  });

  @override
  State<WeatherInput> createState() => _WeatherInputState();
}

class _WeatherInputState extends State<WeatherInput> {
  late TextEditingController _controller;
  DateTime? selectedDate = DateTime.now();

  Future<void> _selectDate() async {
    final DateTime? pickedDate = await showDatePicker(
      context: context,
      initialDate: DateTime.now(),
      firstDate: DateTime.now().copyWith(month: 1, day: 1),
      lastDate: DateTime.now().copyWith(month: 12, day: 31),
    );

    setState(() {
      selectedDate = pickedDate;
    });
  }

  @override
  void initState() {
    super.initState();
    _controller = TextEditingController();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 320,
      padding: const EdgeInsets.all(16),
      child: Card(
        elevation: 4,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
        child: Padding(
          padding: const EdgeInsets.all(24.0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Text("Location", style: TextStyle(fontWeight: FontWeight.bold) ),
              const SizedBox(height: 8),
              TextField(decoration: InputDecoration(border: OutlineInputBorder()), controller: _controller,),
              const SizedBox(height: 20),
              SizedBox(
                width: double.infinity,
                height: 50,
                child: OutlinedButton(
                  style: OutlinedButton.styleFrom(
                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),
                  ),
                  onPressed: () {
                    widget.onFetchRequest(_controller.text, selectedDate!);
                  },
                  child: const Text("Get Forecast", style: TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold)),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
```

2. Edit `lib/genui_utils.dart` to append the UI instruction to `systemInstruction`:
```dart
const systemInstruction = '''
  ## PERSONA
  You are a meteorologist.

  ## GOAL
  Work with me to produce of weather forecasts.

  ## RULES

  Do not offer opinions unless I ask for them.

  ## PROCESS
  ### Planning
  *   Ask me for a location to check the weather.
  *   Follow up and ask for a date if not provided.
  *   Synthesize a list of weather forecasts from the provided information.
  *   Where available, you will use tool calls to retreive the info (not implemented yet)
  *   Advise if you are pulling the data from a real source or making it up.
  *   Ask clarifying questions if you need to.
  *   Respond to my suggestions for changes to date or location, if I have any.

  ## USER INTERFACE
  * To request the location to retreive weather, create an instance of the WeatherInput
  catalog item.
''';
```
*(Hint: Make sure the rest of `genui_utils.dart` remains intact.)*

3. Edit `lib/main.dart` to import the new catalog item and add it to `BasicCatalogItems.asCatalog().copyWith(...)`:
Add this import at the top:
```dart
import 'package:genui_workshop/catalog/weather_input.dart';
```
And in `initState`, modify `catalog = BasicCatalogItems.asCatalog().copyWith();` to:
```dart
    catalog = BasicCatalogItems.asCatalog().copyWith(
      newItems: [weatherInput],
    );
```

