diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..af4a851
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,60 @@
+## A streamlined .gitignore for modern .NET projects
+## including temporary files, build results, and
+## files generated by popular .NET tools. If you are
+## developing with Visual Studio, the VS .gitignore
+## https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+## has more thorough IDE-specific entries.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/Dotnet.gitignore
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+
+# dotenv environment variables file
+.env
+
+# Others
+~$*
+*~
+CodeCoverage/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+temp
+nuget.config
\ No newline at end of file
diff --git a/Photino-Boilerplate.csproj b/Photino-Boilerplate.csproj
new file mode 100644
index 0000000..2b7ed89
--- /dev/null
+++ b/Photino-Boilerplate.csproj
@@ -0,0 +1,25 @@
+
+
+ Exe
+ net8.0
+ AnyCPU
+ Photino_Boilerplate
+ enable
+ enable
+ false
+
+
+
+ $([System.IO.Path]::Combine('$(PkgBrikPackager)', 'lib', 'net8.0', 'BrikPackager.dll'))
+ $([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', 'src', 'resources', 'renderer'))
+ $([System.IO.Path]::Combine('$(TargetDir)', 'root.dat'))
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Photino-Boilerplate.sln b/Photino-Boilerplate.sln
new file mode 100644
index 0000000..b092ffb
--- /dev/null
+++ b/Photino-Boilerplate.sln
@@ -0,0 +1,24 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.2.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Photino-Boilerplate", "Photino-Boilerplate.csproj", "{5FF73963-D009-62ED-7350-FF17EC625A26}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5FF73963-D009-62ED-7350-FF17EC625A26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5FF73963-D009-62ED-7350-FF17EC625A26}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5FF73963-D009-62ED-7350-FF17EC625A26}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5FF73963-D009-62ED-7350-FF17EC625A26}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {5D254170-B473-471E-AD56-26A8F4C4189E}
+ EndGlobalSection
+EndGlobal
diff --git a/README.md b/README.md
index 7007b46..32c83c3 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-# PhotinoBase
+# Photino-Boilerplate
diff --git a/src/main/Program.cs b/src/main/Program.cs
new file mode 100644
index 0000000..2f6371f
--- /dev/null
+++ b/src/main/Program.cs
@@ -0,0 +1,78 @@
+using System.Reflection;
+using System.Text.Json;
+using BrikPackager;
+using PhotinoBoilerplate.Utils;
+using Photino.NET;
+
+namespace PhotinoBoilerplate;
+
+class Program{
+
+ public static readonly JsonSerializerOptions _jsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
+ private static readonly string __dirname = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
+
+ [STAThread]
+ static void Main(string[] args) {
+ CreateMainWindow().WaitForClose();
+ }
+
+ public static PhotinoWindow CreateMainWindow() {
+ BrikPackage bpkg = new BrikPackage(Path.Combine(__dirname, "root.dat"), 66);
+ List entries = bpkg.ListEntries();
+ var window = new PhotinoWindow()
+ .SetTitle("Photino Boilerplate")
+ .SetUseOsDefaultLocation(false)
+ .SetUseOsDefaultSize(false)
+ .RegisterCustomSchemeHandler("http", (object sender, string scheme, string url, out string contentType) =>{
+ Uri uri = new Uri(url);
+ switch (uri.Host){
+ case "internal":
+ string internalPath = uri.AbsolutePath;
+ contentType = MimeHelper.GetMimeType(uri.AbsolutePath);
+ byte[] fileData = bpkg.GetFileBytes(internalPath.TrimStart('/'));
+ return fileData != null ? new MemoryStream(fileData) : null;
+ default:
+ contentType = null!;
+ return null;
+ }
+ });
+
+ window.WindowCreated += (sender, e) => {
+ SetupBridge(window);
+ WindowHelper.setSize(window, 900, 600);
+ window.Center();
+ };
+
+
+ window.Load("http://internal/index.html");
+
+ return window;
+ }
+
+ public static void SetupBridge(PhotinoWindow window) {
+ window.RegisterWebMessageReceivedHandler(async (object? sender, string message) => {
+ try {
+ var json = JsonDocument.Parse(message);
+ string requestId = json.RootElement.GetProperty("requestId").GetString()!;
+ string method = json.RootElement.GetProperty("functionName").GetString()!;
+ var jsonPayload = json.RootElement.GetProperty("payload");
+ var pw = (PhotinoWindow)sender!;
+
+ object? payload = null;
+
+ switch (method) {
+ case "hello::world":
+ payload = "Hello from C#";
+ break;
+
+ }
+
+ var response = new { requestId, payload };
+ window.SendWebMessage(JsonSerializer.Serialize(response, _jsonOptions));
+ } catch (Exception ex) {
+ Console.WriteLine($"Error stacktrace: {ex.StackTrace}");
+ Console.WriteLine($"Bridge error: {ex.Message}");
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/main/helpers/Window.cs b/src/main/helpers/Window.cs
new file mode 100644
index 0000000..91ed8cb
--- /dev/null
+++ b/src/main/helpers/Window.cs
@@ -0,0 +1,29 @@
+using Photino.NET;
+using System.Drawing;
+
+namespace PhotinoBoilerplate.Utils;
+
+public static class WindowHelper {
+
+ private const float StandardDpi = 96.0f;
+
+
+
+ public static Size GetScaledSize(PhotinoWindow window, int logicalWidth, int logicalHeight) {
+ float currentDpi = window.ScreenDpi > 0 ? window.ScreenDpi : StandardDpi;
+ float scaleFactor = currentDpi / StandardDpi;
+
+ return new Size(
+ (int)(logicalWidth * scaleFactor),
+ (int)(logicalHeight * scaleFactor)
+ );
+ }
+
+ public static void setSize(PhotinoWindow window, int width, int height) {
+ Size targetSize = GetScaledSize(window, width, height);
+ window
+ .SetResizable(true)
+ .SetSize(targetSize)
+ .SetMinSize(targetSize.Width, targetSize.Height);
+ }
+}
\ No newline at end of file
diff --git a/src/resources/renderer/assets/css/index.css b/src/resources/renderer/assets/css/index.css
new file mode 100644
index 0000000..055c3c5
--- /dev/null
+++ b/src/resources/renderer/assets/css/index.css
@@ -0,0 +1,45 @@
+@import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
+
+* {
+ margin: 0px;
+ padding: 0px;
+ box-sizing: border-box;
+}
+
+main {
+ display: flex;
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ right: 0px;
+ bottom: 0px;
+ flex-wrap: wrap;
+ flex-direction: column;
+ gap: 10px;
+ color: #cecece;
+ background-color: #404551;
+ align-items: center;
+ justify-content: center;
+ font-family: "Poppins", sans-serif;
+}
+
+button {
+ cursor: pointer;
+ padding: 7px 7px 7px 7px;
+ color: #cecece;
+ font-weight: 500;
+ border: none;
+ outline: none;
+ border-radius: 5px;
+ background-color: #c8850a;
+ transition: .3s all;
+ font-family: "Poppins", sans-serif;
+}
+
+button:hover {
+ filter: brightness(0.95);
+}
+
+button:active {
+ filter: brightness(1.10);
+}
diff --git a/src/resources/renderer/assets/js/index.js b/src/resources/renderer/assets/js/index.js
new file mode 100644
index 0000000..b6e9954
--- /dev/null
+++ b/src/resources/renderer/assets/js/index.js
@@ -0,0 +1,4 @@
+async function callCSharp() {
+ const result = await system.call("hello::world")
+ alert(result)
+}
\ No newline at end of file
diff --git a/src/resources/renderer/assets/js/ipc.js b/src/resources/renderer/assets/js/ipc.js
new file mode 100644
index 0000000..6f54d74
--- /dev/null
+++ b/src/resources/renderer/assets/js/ipc.js
@@ -0,0 +1,34 @@
+const system = {
+ _pendingRequests: new Map(),
+
+ init: function() {
+ window.external.receiveMessage(response => {
+ try {
+ const res = JSON.parse(response)
+ if (res.requestId && this._pendingRequests.has(res.requestId)) {
+ const { resolve } = this._pendingRequests.get(res.requestId)
+ this._pendingRequests.delete(res.requestId)
+ resolve(res.payload)
+ }
+ } catch (e) {
+ console.error("Erreur format message :", e)
+ }
+ })
+ },
+
+ call: function(functionName, data = {}) {
+ return new Promise((resolve, reject) => {
+ const requestId = Math.random().toString(36).substring(7)
+
+ this._pendingRequests.set(requestId, { resolve, reject })
+
+ window.external.sendMessage(JSON.stringify({
+ requestId: requestId,
+ functionName: functionName,
+ payload: data
+ }))
+ })
+ }
+}
+
+system.init()
\ No newline at end of file
diff --git a/src/resources/renderer/index.html b/src/resources/renderer/index.html
new file mode 100644
index 0000000..0306745
--- /dev/null
+++ b/src/resources/renderer/index.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Bienvenue dans Photino
+
+
+
+
+
+
+
+
+
\ No newline at end of file