Skip to content

feat: add example app#2

Merged
sirily11 merged 1 commit intomainfrom
example
Apr 3, 2026
Merged

feat: add example app#2
sirily11 merged 1 commit intomainfrom
example

Conversation

@sirily11
Copy link
Copy Markdown
Contributor

@sirily11 sirily11 commented Apr 3, 2026

No description provided.

Copilot AI review requested due to automatic review settings April 3, 2026 18:31
@sirily11 sirily11 enabled auto-merge (squash) April 3, 2026 18:31
@autopilot-project-manager autopilot-project-manager bot added the enhancement New feature or request label Apr 3, 2026
@sirily11 sirily11 merged commit facfd0a into main Apr 3, 2026
3 checks passed
@sirily11 sirily11 deleted the example branch April 3, 2026 18:32
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a macOS example app that demonstrates generating JSONRenderSwift Spec JSON via an AI provider and live-rendering it, while also enhancing the core library’s spec/schema guidance and decoding behavior to better support AI-generated JSON.

Changes:

  • Added Spec.schemaDescription to provide an LLM-friendly schema description for the JSONRenderSwift output format.
  • Updated UIElement decoding to tolerate missing props by defaulting to an empty dictionary.
  • Introduced a full Xcode example app project (views, model, AI service integration), plus starter unit/UI test targets and app assets.

Reviewed changes

Copilot reviewed 17 out of 19 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Sources/JSONRenderSwift/Models/Spec.swift Adds LLM schema description and custom UIElement decoding defaults.
example/example/AIService.swift Adds AI provider/model factory used by the example app.
example/example/ChatView.swift Implements the chat UI for prompting UI generation.
example/example/ChatViewModel.swift Implements streaming generation, JSON extraction, and persistence for the example app.
example/example/ContentView.swift Main split UI (chat + JSON/live preview).
example/example/PreviewPanel.swift Adds JSON vs Live Render preview tabs using JSONRenderer.
example/example/SettingsView.swift Adds settings UI for provider, endpoint, API key, and model selection.
example/example/exampleApp.swift App entry point and macOS Settings scene.
example/example/Assets.xcassets/Contents.json Adds asset catalog metadata.
example/example/Assets.xcassets/AccentColor.colorset/Contents.json Adds accent color set metadata.
example/example/Assets.xcassets/AppIcon.appiconset/Contents.json Adds app icon set metadata.
example/exampleTests/exampleTests.swift Adds template unit test target source.
example/exampleUITests/exampleUITests.swift Adds template UI test target source.
example/exampleUITests/exampleUITestsLaunchTests.swift Adds UI test launch/screenshot template.
example/example.xcodeproj/project.pbxproj Adds Xcode project configuration and package dependencies.
example/example.xcodeproj/project.xcworkspace/contents.xcworkspacedata Adds workspace metadata.
example/example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Pins SwiftPM dependencies for the example project.
example/appicon.icon/icon.json Adds Icon Composer configuration for the app icon.
example/appicon.icon/Assets/json-render-avatar-icon-1024x1024.png Adds the source image used to generate the app icon.
Files not reviewed (1)
  • example/example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

on = try container.decodeIfPresent([String: ActionBindingOrArray].self, forKey: .on)
`repeat` = try container.decodeIfPresent(RepeatConfig.self, forKey: .repeat)
}

Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UIElement now implements init(from:) while still conforming to Codable, but there is no corresponding encode(to:). In Swift, providing a custom init(from:) prevents automatic synthesis of encode(to:), so this will break compilation unless encode(to:) is added (or the conformance is changed to Decodable).

Suggested change
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(type, forKey: .type)
try container.encode(props, forKey: .props)
try container.encodeIfPresent(children, forKey: .children)
try container.encodeIfPresent(visible, forKey: .visible)
try container.encodeIfPresent(on, forKey: .on)
try container.encodeIfPresent(`repeat`, forKey: .repeat)
}

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +28
struct SettingsView: View {
@AppStorage("providerType") private var providerType: String = AIProviderType.openai.rawValue
@AppStorage("apiEndpoint") private var apiEndpoint: String = ""
@AppStorage("apiKey") private var apiKey: String = ""
@AppStorage("modelName") private var modelName: String = ""
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API key is persisted via @AppStorage("apiKey") (UserDefaults) which stores the value in plaintext on disk. For real credentials, prefer storing/retrieving from Keychain (and keep @AppStorage only for non-sensitive settings).

Copilot uses AI. Check for mistakes.
let state = PersistedState(messages: messages, currentJSON: currentJSON)
do {
let data = try JSONEncoder().encode(state)
try data.write(to: Self.stateFileURL)
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saveState() writes directly to the target file without .atomic/temp-file semantics. If the app is terminated mid-write, the JSON can be corrupted and subsequent loads will fail. Consider using data.write(to:options: .atomic) (and/or writing to a temporary file then moving).

Suggested change
try data.write(to: Self.stateFileURL)
try data.write(to: Self.stateFileURL, options: .atomic)

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +88
} catch {
// No saved state or failed to load - start fresh
print("[ChatViewModel] No saved state or failed to load: \(error)")
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loadState() logs an error for the common “file not found” case, which will add noise on first launch. Consider handling the “no such file” error separately (silently start fresh) and only logging unexpected decoding/IO errors.

Suggested change
} catch {
// No saved state or failed to load - start fresh
print("[ChatViewModel] No saved state or failed to load: \(error)")
} catch let error as CocoaError where error.code == .fileReadNoSuchFile {
// No saved state yet - start fresh silently
} catch {
// Failed to read or decode saved state - start fresh and log the unexpected error
print("[ChatViewModel] Failed to load state: \(error)")

Copilot uses AI. Check for mistakes.
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = P9KK452K8P;
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The project file hard-codes a specific DEVELOPMENT_TEAM value. This commonly prevents other contributors from building/signing the example app without editing the project. Consider removing the team ID from the checked-in project (or using a build setting override / leaving it blank).

Suggested change
DEVELOPMENT_TEAM = P9KK452K8P;

Copilot uses AI. Check for mistakes.
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 26.2;
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MACOSX_DEPLOYMENT_TARGET is set to 26.2 in the project. Please verify this is the intended minimum supported macOS version, since an overly high deployment target will make the example app impossible to build/run on most systems and CI images.

Suggested change
MACOSX_DEPLOYMENT_TARGET = 26.2;
MACOSX_DEPLOYMENT_TARGET = 13.0;

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants