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
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ packages/
superdeck/ # Flutter widgets and presentation components
cli/ # superdeck CLI tool (setup, build/watch, version)
builder/ # Deck parsing, serialization, and build/watch pipeline (Dart-only)
playground/ # SuperDeck Wizard: AI deck generation, presenting, saving
playground/ # SuperDeck Wizard: AI deck generation, presenting, exporting
plugins/pdf/ # PDF export plugin
demo/ # Sample presentation app
docs/ # User-facing documentation (MDX format)
Expand All @@ -33,7 +33,7 @@ docs/ # User-facing documentation (MDX format)
- **superdeck**: Flutter widgets, DeckController, navigation, thumbnail/capture services, theme system
- **cli**: CLI commands for project setup and building slides
- **builder**: Markdown deck parsing, serialization, build/watch orchestration, and build plugins
- **playground**: AI deck generation (the Wizard), present mode, and the saved-deck library
- **playground**: AI deck generation (the Wizard), present mode, and deck export
- **plugins/pdf**: PDF capture and export UI

## Environment Setup
Expand Down
44 changes: 14 additions & 30 deletions packages/playground/README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
# playground

The SuperDeck Wizard. One flow: describe a presentation, review the outline it
plans, approve it, present the deck, and save it. Package name kept as
plans, approve it, present the deck, and export it. Package name kept as
`playground` for now.

Generated decks live in memory. The app does not open arbitrary Markdown,
watch files, or auto-save; a deck is written only when the reader asks for it.
The deck lives in memory for the run. The app does not open Markdown files or
keep a library of decks; a deck leaves the app only when the reader exports it.

## What a saved deck is
## Exporting a deck

Three files that travel together in your SuperDeck folder:
**Export deck** saves a zip through the platform's save dialog:

```
My talk.md the Markdown the generation produced
My talk.assets/ the artwork it refers to by bare filename
My talk.deck.json name, timestamp, asset list, and the theme selection
slides.md the Markdown the generation produced
assets/ its generated artwork
```

The manifest stores the theme's catalog id, version and density, not resolved
colours, so a deck reopened later is recognised rather than guessed at. A deck
whose manifest is missing or unreadable still opens; it opens without its
theme.

**Moving, copying or sharing a deck has to include its asset directory**, or
its images stop resolving. Saving the same deck twice keeps both copies
("My talk", then "My talk 2") — a save never replaces a deck you already have.

Saving is macOS-only for now: it needs a folder you pick once, which the app
remembers. Generating and presenting work anywhere; the save action is simply
absent where decks cannot be stored.
`slides.md` refers to each image as `assets/<file>`, so the unzipped folder is
a SuperDeck project: build it with the CLI and present it from any SuperDeck
app. Declare `assets/` in that app's `pubspec.yaml` to bundle the images for
release and web builds. The export carries the Markdown and artwork, not the
generated theme.

## Layers (folders, single package)

Expand All @@ -37,12 +29,11 @@ lib/
main.dart
app/ # router.dart + providers.dart (app-root DI)
core/ # shared cross-feature domain + data
result.dart # Result<T>
domain/ # stores (document, customization), design catalogs
domain/ # customization store, design catalogs
data/ # data_sources (asset stores, deck loader), mappers
features/
ai/ # the Wizard, the generation engine, image generation
library/ # saved decks: domain / data / presentation / routes
export/ # the deck as a SuperDeck project zip
presentation/ # present mode
```

Expand Down Expand Up @@ -159,10 +150,3 @@ fvm flutter test test_live/ai_generation/ai_generation_smoke_test.dart \
Add `--dart-define=LIVE_DEBUG_LAYOUT=true` to include the section, block,
margin, and padding guides in the recaptured slide PNGs and contact sheet.
Normal captures remain clean by default.

## Deck files

On first launch, choose a parent directory for deck storage. The app creates a
`SuperDeck` folder inside it and remembers access with a macOS security-scoped
bookmark. The saved-deck library lists the decks in that folder and opens them
read-only for presenting. The Wizard does not open arbitrary Markdown files.
27 changes: 0 additions & 27 deletions packages/playground/dcm_baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,6 @@
"99914b932bd37a50b983c5e7c90ae93b"
]
},
"lib/core/data/data_sources/security_scoped_file_access.dart": {
"member-ordering": [
"be8c26dcc636a143b78001de86957301",
"4d906b08741be42f24bff407f0b17938",
"1430c4571c14f58ecac407876fdacbe2",
"74d2d4912fc7084d7933cf07e59a738d",
"ce91d284738a04ce3ae951f7c61efa8d"
],
"newline-before-return": [
"a7b69a9b65d6bb7620e797ff51b1f2a2",
"c9db1f09a26ca1c96a59cea77cf29a8e",
"004d60a501680fe4a801c1f382091a6c",
"9d1bed3be3f428ef16a7bc10fb4f04d1",
"eefb853f7fffca0c5b6d150b8eaa69df"
]
},
"lib/core/domain/design/generated_deck_theme_factory.dart": {
"prefer-shorthands-with-enums": [
"f3d70c6aa77da74309195ab874fff66d",
Expand Down Expand Up @@ -121,12 +105,6 @@
"959b7175f88493905e3c324c2bf6f97d"
]
},
"lib/core/result.dart": {
"member-ordering": [
"85eca8e6b45775b517ebcc6aab8021d0",
"00c8c3a7775b4bd83b4c7627c1029a39"
]
},
"lib/features/ai/generation/core/debug_logger.dart": {
"member-ordering": [
"c9e8d09211e0b5eaac505b8ea7fb89e6"
Expand Down Expand Up @@ -845,11 +823,6 @@
"7619ac479ac9f2834cfe7d877347194d"
]
},
"lib/features/ai/wizard/core/ui/widgets/header.dart": {
"arguments-ordering": [
"801979137471c1e5fb1750d69c099bcf"
]
},
"lib/features/ai/wizard/core/utils/color_utils.dart": {
"newline-before-return": [
"ac84b6615d6391fc8cb6a100c0b2aad0",
Expand Down
38 changes: 4 additions & 34 deletions packages/playground/lib/app/providers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,9 @@ import 'package:hero_ui/hero_ui.dart';
import 'package:provider/provider.dart';
import 'package:superdeck/superdeck.dart';

import '../core/data/data_sources/deck_library_asset_store.dart';
import '../core/data/data_sources/memory_asset_cache_store.dart';
import '../core/data/data_sources/memory_deck_loader.dart';
import '../core/domain/stores/deck_customization_store.dart';
import '../core/domain/stores/deck_document_store.dart';
import '../features/library/data/mac_os_deck_library.dart';
import '../features/library/domain/deck_library.dart';
import '../features/library/domain/deck_library_controller.dart';

const _debugDeckLayout = bool.fromEnvironment('SUPERDECK_DEBUG_LAYOUT');

Expand All @@ -25,13 +20,10 @@ const _debugDeckLayout = bool.fromEnvironment('SUPERDECK_DEBUG_LAYOUT');
/// `PresentationPage` hands `DeckController` straight to SuperDeck's own
/// `DeckPresenter`, which reads slides internally — no bridge store.
class AppProviders extends StatelessWidget {
const AppProviders({required this.child, this.deckLibrary, super.key});
const AppProviders({required this.child, super.key});

final Widget child;

/// Overrides the macOS deck library in tests and on other platforms.
final DeckLibrary? deckLibrary;

@override
Widget build(BuildContext context) {
// Resolve theme tokens here (listening is allowed in build) rather than
Expand All @@ -46,29 +38,16 @@ class AppProviders extends StatelessWidget {
dispose: (_, loader) => loader.dispose(),
),
Provider<MemoryAssetCacheStore>(create: (_) => MemoryAssetCacheStore()),
ChangeNotifierProvider(create: (_) => DeckDocumentStore(markdown: '')),
Provider<DeckLibrary>(
create: (_) => deckLibrary ?? MacOsDeckLibrary(),
dispose: (_, library) => library.dispose(),
),
Provider(
create: (ctx) => DeckLibraryAssetStore(
library: ctx.read(),
// Typed explicitly: generated artwork has to land in the store the
// thumbnails read, not in any store that happens to be provided.
fallback: ctx.read<MemoryAssetCacheStore>(),
),
),
Provider<DeckController>(
create: (ctx) => DeckController(
deckLoader: ctx.read<MemoryDeckLoader>(),
options: DeckOptions(debug: _debugDeckLayout),
// Slide artwork follows the open deck; thumbnails are derived
// from it and stay in memory.
// Generated artwork and the thumbnails derived from it both live
// in memory for the run.
thumbnailService: ThumbnailService(
cacheStore: ctx.read<MemoryAssetCacheStore>(),
),
assetCacheStore: ctx.read<DeckLibraryAssetStore>(),
assetCacheStore: ctx.read<MemoryAssetCacheStore>(),
),
dispose: (_, controller) => controller.dispose(),
lazy: false,
Expand All @@ -81,15 +60,6 @@ class AppProviders extends StatelessWidget {
foreground: foreground,
),
),
ChangeNotifierProvider(
create: (ctx) => DeckLibraryController(
library: ctx.read(),
documentStore: ctx.read(),
deckLoader: ctx.read(),
customizationStore: ctx.read(),
assetStore: ctx.read(),
),
),
],
child: child,
);
Expand Down
7 changes: 1 addition & 6 deletions packages/playground/lib/app/router.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import 'package:go_router/go_router.dart';

import '../features/ai/wizard/routes/routes.dart';
import '../features/library/routes/routes.dart';
import '../features/presentation/routes/routes.dart';

/// The app's [GoRouter], composing each feature's routes.
GoRouter createRouter({String initialLocation = '/'}) {
return GoRouter(
routes: [
...wizardRoutes(),
...libraryRoutes(),
...presentationRoutes(),
],
routes: [...wizardRoutes(), ...presentationRoutes()],
initialLocation: initialLocation,
);
}
54 changes: 0 additions & 54 deletions packages/playground/lib/core/data/data_sources/deck_file.dart

This file was deleted.

This file was deleted.

Loading
Loading