Giter Club home page Giter Club logo

squirrel.windows's Introduction

README.md

Contributors Needed

We are looking for help with maintaining this important project - please read the discussion in #1470 for more information.


Squirrel: It's like ClickOnce but Works™

Build Status

Squirrel is both a set of tools and a library, to completely manage both installation and updating your Desktop Windows application, written in either C# or any other language (i.e., Squirrel can manage native C++ applications).

Squirrel uses NuGet packages to create installation and update packages, which means that you probably already know most of what you need to create an installer.

What Do We Want?

Windows apps should be as fast and as easy to install and update as apps like Google Chrome. From an app developer's side, it should be really straightforward to create an installer for my app, and publish updates to it, without having to jump through insane hoops.

  • Integrating an app to use Squirrel should be extremely easy, provide a client API, and be developer friendly.
  • Packaging is really easy, can be automated, and supports delta update packages.
  • Distributing should be straightforward, use simple HTTP updates, and provide multiple "channels" (a-la Chrome Dev/Beta/Release).
  • Installing is Wizard-Free™, with no UAC dialogs, does not require reboot, and is .NET Framework friendly.
  • Updating is in the background, doesn't interrupt the user, and does not require a reboot.

Refer to our full list of goals for integrating, packaging, distributing, installing, and updating.

Documentation

See the documentation Table of Contents for an overview of the available documentation for Squirrel.Windows. It includes a Getting Started Guide as well as additional topics related to using Squirrel in your applications.

Building Squirrel

For the impatient:

git clone --recursive https://github.com/squirrel/squirrel.windows
cd squirrel.windows
devbuild.cmd

See Contributing for additional information on building and contributing to Squirrel.

License and Usage

See COPYING for details on copyright and usage of the Squirrel.Windows software.

squirrel.windows's People

Contributors

aarnott avatar anaisbetts avatar barrythepenguin avatar bitdisaster avatar christianrondeau avatar damieng avatar dennisameling avatar flagbug avatar geertvanhorrik avatar gojanpaolo avatar horb avatar humbertoc26 avatar johnthomson avatar keboo avatar kevfromireland avatar kristof-mattei avatar lennartajansson avatar lukeskinner avatar maxbrunsfeld avatar mwcampbell avatar neilsorensen avatar nullif avatar patroza avatar peters avatar ran-intendu avatar robmen avatar shiftkey avatar shoelzer avatar thieum avatar willdean avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

squirrel.windows's Issues

Using Squirrel on a .Net 4.0 project

When I:
PM> Install-Package squirrel.windows

Amongst other things, I get:
Install failed. Rolling back...
Install-Package : Could not install package 'Splat 1.4.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.0', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

Thinking I could use the binaries from the releases section instead, but isn't this still going to be a problem?

Add some meta-data to Setup.exe

The Setup.exe file should have the information from the latest nupkg file. Right now, it doesn't look very professional :)

image

This being said, I'm bundling a second addition: changing the icon for Setup.exe. If you feel this should be a second issue, let me know.

File Groups

Clickonce has feature called file groups - we're using it as a way to download plugins (each .dll is a group so user can download them and we're loading them later with Ninject). Initially we only have 'shell' of application and user is selecting which modules are interesting for him.

Is there any way to do something similar with Squirrel?

Synchronise the RELEASES and nupkg files with Squirrel.exe

Here's the issue I'm trying to solve: I'm working on three machines. One at the office, one at home and a Surface Pro 2 tablet. From any location, I want to build and deploy a new release.

In order to do that, I need to have at least the previous nupkg, and I must have the complete RELEASES file on the machine I'm on.

In other words it's a classic "single source of truth" problem.

At the moment, the only source of truth I can think of is the actual releases directory. Also, Update.exe already has the required functionality to download and read the RELEASES file.

Therefore, the best way I can think of to solve the issue is to add a new functionality to Squirrel.exe --releasify (or maybe in a separate call to Squirrel.exe with a different flag that I'd call at build time) that would:

  1. Download the RELEASES file and overwrite whatever is in the Releases directory
  2. Download the latest nupkg referenced in the RELEASES file

I'm thinking of something like this:

Squirrel.exe --synchronize http://my-server/releases-directory

My second best idea would be to do the same thing myself (meaning I'll have to re-develop RELEASES parsing and nupkg downloading), but I'm sure I'm not the only one with more than one machine; or, maybe in a project with multiple build servers, etc.

Any other ideas to solve this problem?

Setup: If the install or the app launch fails, feedback should be given to the user

I had a first run of user installs with my app, GoToWindow. It went ok for the most part, but I had some negative feedback.

One of them ran the installer, but nothing happened. The software was already installed, this is already logged as #69.

Another said that nothing happened. I'm not sure what the problem was exactly, and they couldn't find a SquirrelSetup.log file (I didn't push the issue).

I think that if for whatever reason something doesn't work, including:

  • The setup itself
  • Any of the app launches with --squirrel-*
  • If the first run returns within some time span with a non-zero exit code

a clear error message should be shown to the user, including an easy way to get the log file so they can send it back to the application developer.

Even better would be an optional "Send error log to the developer", using an email address from the nupkg, but I'm getting ahead of myself :)

I believe an error is frustrating, but so much less than no feedback at all.

Bundle the icon with the Setup rather than downloading it at install-time

I think being able to install offline should not behave differently once I downloaded Setup.exe

(Note that I didn't double-confirm this)

In practice, it really doesn't change much but still, something to look into :)

My idea: if it's bundled in Setup.exe, you can extract it from "yourself", so you'll solve #55 and this one at the same time :)

Initial Hack of Update.exe

Need to create an initial version of Update.exe which can do the things listed, at least Install and Uninstall. Depends on #7.

Join the Squirrel Chat Room

If you're interested in Squirrel.Windows.Next and want to get involved, the best way is via joining our Slack room on the topic:

Getting In

Email [email protected] with the Email address you'd like to join up with and I can send you an invite

Provide a way to "carry" content across releases

I'm not sure about this one, but here goes.

My application has a configuration file (App.config), a log file and a Plugins directory where users can drop their extensions.

Because of the way Squirrel works (creating a different folder per version), those files are lost "in the midst of the past". My best option now is to have my app create another folder (e.g. in %AppData%) and put every file that can be modified there.

If you think this is the way to go, you can close this issue (and this can serve as a reference for people with similar wants), otherwise what do you think of being able to "carry" files over releases? Or maybe Squirrel could be "responsible" of setting up a data directory shared between version?

My intention is to setup a shared directory in %AppData%\MyApp when my app is run with --squirrel-install.

Unable to parse release entry

The are definitely some strange going on here. Squirrel is unable to parse my RELEASES file using DownloadUrl. I've tried uploading it to both Azure and a storage site in norway with the same result.

Using DownloadStringTaskAsync instead resolves the problem. What is going on? You can download the RELEASES file here.

It seems like an invisible space is being appended to the start of the FILE. Adding .Substring(1) here also resolves the problem.

I've not manually modified the RELEASES file and it's being uploaded using curl. I've also tried using WinSCP, but the result is the same.

Calling UpdateApp() When there is no update causes the application to hang

This code:

            try
            {
                using (
                    var mgr = new UpdateManager(@"http://localhost.fiddler:55910/testinst", "YourAppName",
                        FrameworkVersion.Net45))
                {
                    ReleaseEntry result = await mgr.UpdateApp();
                    MessageBox.Show("updated");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

cause the application running it to hang if the app doesn't actually need to be updated. hang is in SingleGlobaIinstance.Dispose

Should log shortcuts as added in an application

In my UserManager application I am running the following code:

protected override void OnStartup(StartupEventArgs e)
        {
            if (!Debugger.IsAttached)
            {
                AppDomain currentDomain = AppDomain.CurrentDomain;
                currentDomain.UnhandledException += ExceptionHandler;
            }

            using (var mgr = CreateUpdateManager())
            {
                // Note, in most of these scenarios, the app exits after this method
                // completes!
                SquirrelAwareApp.HandleEvents(
                    onInitialInstall: version =>
                    {
                        MessageBox.Show(string.Format("installed version: {0}. Current Version: {1}", version,
                            GetType().GetTypeInfo().Assembly.GetName().Version));
                        mgr.CreateShortcutForThisExe();
                    },
                    onAppUpdate: version =>
                    {
                        MessageBox.Show(string.Format("updated to version: {0}. Current Version: {1}", version,
                            GetType().GetTypeInfo().Assembly.GetName().Version));
                        mgr.CreateShortcutForThisExe();
                    },
                    onAppUninstall: version =>
                    {
                        MessageBox.Show("Uninstall");
                        mgr.RemoveShortcutForThisExe();
                    },
                    onFirstRun: () => { }
                    );
            }

But the shortcut icons are never being created. The message box is appearing, so I know that the code is being called. Because there is no logging I don't really know how to resolve this.

Would be useful as there was logging, perhaps put into the app folder when shortcuts are added within the application.

In my main application I create the shortcut icons without using the easy API, and that works (although admittedly also no logging).

Stefan

Fix NuGet assembly reference resolution

As the README says, use a Targets-generated file to inform the package generator what files to include in the Release package, instead of trying to mimic what NuGet does when it adds a package reference

Installation directory per user or for all users

Hi,

I need my application below %programfiles% instead of %appdata%.
So it would be great if there would be an option for the installation directory.
For example "per user" -> %appdata% or "for all" -> %programfiles%.

Greetings

Real Documentation

We need to have good documentation / best practices for how to write proper installers and updaters, and how to be Squirrel-Aware™

Rerun setup opens app with firstrun

If I rerun set up and I have already installed the current version, then it tells me that it is running for the first time, which it isn't because it's already been installed, so it's not really an issue, it's more a question of clarifying that first run happens whenever the software is run from setup, not just the first time that it is run from setup, if that makes sense :-)

Support for windows service

It should be pretty simple adding support for windows services. Keeping it really simple you can reuse the existing installation structure %appdata%\app\0.1.1.

The only change really is that after you have "installed" the app, you just kill the existing service and execute myservice.exe install and you're good.

Obvious stuff like waiting for the service to stop (give a minute or kill it).

UpdateApp() causes app to start with -firstrun

This is a slightly different issue then I raised in the previous issue. When you are updating the application, it is run with firstrun. I actually don't want to run at all as part of the update, apart from the -update option. I need to exit my application first before I can run it again. The way that it's working currently is that the application is being updated and I've now got two of them running at the same time.

Provide a way to mark a version as "beta" / pre-release channel

Probably low priority, but in the spirit of sharing ideas and feedback...

When I deploy an application in production, I want to make sure everything runs smoothly before showing it to the world.

Now, I only see one choice: make two Releases directories, and in my App.config select which "channel" I want to run use. This works, but means I have to duplicate my releases folder.

What would be nice would be to simply be able to "flag" releases as pre-release, and allow configuring Squirrel to ignore pre-release versions or not. This way, I can simply switch the version once it has been tested enough.

As always, the general idea is what matters here. Alternatives to pre-release deployment are welcome!

When Releases\MyProject.0.0.0.nupkg already exists, replace it

Right now, if I re-package a project several times (e.g. I change a file in my release folder, run Squirrel --releasify, delete the content of AppData and re-run Setup.exe), my changes are not reflected in the AppData folder.

After some searching, I found out that even if my .nupkg file was indeed correctly re-built, the .nupkg file in the Releases folder was still the old one. Deleting that file and re-running Squirrel --releasify solves the issue.

I believe that Squirrel should either replace the target .nupkg file OR throw an error, but not run successfully if the target file already exists.

Figure out what to do about installation and multiple EXEs

Because we nuked the IAppSetup framework, we now need to come up with an alternate plan for how to choose what shortcuts to create and how to keep them up-to-date.

At minimum, we need to know what EXE to launch once initial install completes, and we could instead ask application authors to do this themselves.

Provide a way to launch the new version after `ApplyReleases`

In short: create a function on UpdateManager to launch the new version.

It should:

  1. Launch Update.exe and provide the current PID
  2. Wait for the specified PID to exit
  3. Launch the new version with a --squirrel-something argument

That's one way, but obviously other implementations of the same general idea would be welcome!


More details.

When updating using ApplyReleases within an application, I have to take the installation path from ApplyReleases, combine it with my expected executable path, launch it and finally close my app. In my case, because I prevent other instances of my application to run, I also have to find a way to launch my new instance with a "special mode" that makes it wait for the current instance to close (wreaking havoc if for some reason the current version does not close).

You already have the tooling to run the correct file after installing, AND you can do it from Update.exe rather than within the app itself.

What do you think? What is otherwise expected of the developer who uses ApplyReleases?

Ability to store the .nupkg files and the RELEASES file in separate folders

I'm using GitHub Pages as my application website, and GitHub Releases. I cannot deploy large files to GitHub Pages, and I cannot provide a stable URL using GitHub Releases. Therefore, I would like to be able to provide a different location for the .nupkg file. Otherwise, I'm stuck on the long run :)

I think it could be easy to do without breaking the RELEASES format.

It now looks like this:

0000000000000000000000000000000000000000000 MyApp-1.0.0-full.nupkg 000000

You'd just have to accept full paths or URLs. Otherwise, it stays relative to the RELEASES file.

0000000000000000000000000000000000000000000 http://my-storage-host/releases/MyApp-1.0.1-full.nupkg 000000

That would be a powerful way to use, say, S3 for releases storage while keeping your own domain name for publishing the RELEASES file. And as a bonus, that would allow for storing "older" releases on a less stable archive host if space is an issue.

Ensure failed delta updates fall back to full updates

It would be awesome if delta updates are supported. Some of our installers are 50mb and right now are shipping all bits for every update we make.

In old squirrel this is really buggy, so we ended up never shipping deltas. You could do this rather easily by added all the new files from the newest nupkg and binary diff all files with the same path from the previous version.

💇 🐹 👡 🍶

What even is this ?

Hi!

I stumbled upon this repository "by accident", browsing github and following links.

Now, by reading the readme, I know that it's better than Squirrel.Windows and how much it differs from it.

But it doesn't answer the question: What is Squirrel.Windows ?

I have absolutely no idea. It could be the killer app/library that I'm looking for without knowing. It could bring world peace. I wouldn't know. There is no way for me to know.

Please fix the readme.

Provide a built-in CLI handler for startup arguments (--squirel-*)

Since most apps will want/need to handle the --squirrel-* startup arguments, I suggest you provide a built-in handler for that. e.g.:

var myHandler = new MyImplementationOfISquirrelStartupArgumentsHandler();
if(SquirrelStartupArgumentsHandler.Handle(myHandler) == SquirrelStartupResult.Exit)
    return;

(Just as an example of the idea).

What do you think? I can provide my implementation back as a pull request if you want.

Customize the time before the loading GIF shows up

It's currently hardcoded to 4 seconds, which I think is way too much. I expect immediate feedback, and even though the app might start immediately, just the .NET JIT may be enough to make me ask myself the question: what is happening? Did it work?

I would personally set it to zero, and even if it just flickers, at least it gives a clue that something happened.

Consider support of NET 40

I will create a PR if you want to support NET 40. I already created a PR for splat, which is one of the dependencies that requires to be NET 40 compatible: reactiveui/splat#80

I can't see any other real missing points in NET 40 why it cannot be supported.

Do not crash if the `%LocalAppData%\MyApp` folder exists, but not the `RELEASES` file

I now get this error:

CheckForUpdateImpl: Failed to load local releases, starting from scratch: System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\username\AppData\Local\MyApp\packages\RELEASES'.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at Squirrel.UpdateManager.CheckForUpdateImpl.LoadLocalReleases(String localReleaseFile)
   at Squirrel.UpdateManager.CheckForUpdateImpl.<CheckForUpdate>d__38.MoveNext()

An missing 'RELEASES' file should be treated like a missing app directory IMHO.

Source sequence doesn't contain any elements when updating

Updating my application gives the following error when there are no updates to download:

System.InvalidOperationException: Source sequence doesn't contain any elements.
   at Squirrel.EnumerableExtensions.ExtremaBy[TSource,TKey](IEnumerable`1 source, Func`2 keySelector, Func`3 compare) in c:\Users\paul\code\squirrel\Squirrel.WindowsNG\src\Squirrel\EnumerableExtensions.cs:line 68
   at Squirrel.EnumerableExtensions.MaxBy[TSource,TKey](IEnumerable`1 source, Func`2 keySelector, IComparer`1 comparer) in c:\Users\paul\code\squirrel\Squirrel.WindowsNG\src\Squirrel\EnumerableExtensions.cs:line 60
   at Squirrel.EnumerableExtensions.MaxBy[TSource,TKey](IEnumerable`1 source, Func`2 keySelector) in c:\Users\paul\code\squirrel\Squirrel.WindowsNG\src\Squirrel\EnumerableExtensions.cs:line 42
   at Squirrel.EasyModeMixin.<UpdateApp>d__11.MoveNext() in c:\Users\paul\code\squirrel\Squirrel.WindowsNG\src\Squirrel\IUpdateManager.cs:line 162
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at WpfApplication2.MainWindow.<Update>d__2.MoveNext() in c:\temp\WpfApplication2\WpfApplication2\MainWindow.xaml.cs:line 45 

When a delta file already exists, either overwrite it or simply use it, rather than crashing

If applying the update failed (e.g. interrupted process), or if the executable that is ran was downloaded manually (e.g. I installed my app, then downloaded it manually and tried to update) it will crash because the delta nupkg already exists.

If the file exists, the best would be to validate it (compare?) and use it, or otherwise simply overwrite it.

Here's the error:

2014-09-20 15:36:12 FATAL GoToWindow - System.IO.IOException: The file 'C:\Users\Christian\AppData\Local\GoToWindow\packages\GoToWindow-0.1.8-delta.nupkg' already exists.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite, Boolean checkHost)
   at System.IO.File.Copy(String sourceFileName, String destFileName)
   at Squirrel.UpdateManager.DownloadReleasesImpl.<>c__DisplayClass5a.<DownloadReleases>b__56(ReleaseEntry x) in c:\Users\paul\code\squirrel\Squirrel.WindowsNG\src\Squirrel\UpdateManager.DownloadReleases.cs:line 39
   at Squirrel.Utility.<>c__DisplayClass11`1.<>c__DisplayClass13.<ForEachAsync>b__10() in c:\Users\paul\code\squirrel\Squirrel.WindowsNG\src\Squirrel\Utility.cs:line 122
   at System.Threading.Tasks.Task.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Squirrel.Utility.<>c__DisplayClass17`1.<>c__DisplayClass19.<<ForEachAsync>b__16>d__1b.MoveNext() in c:\Users\paul\code\squirrel\Squirrel.WindowsNG\src\Squirrel\Utility.cs:line 132
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Squirrel.UpdateManager.DownloadReleasesImpl.<DownloadReleases>d__60.MoveNext() in c:\Users\paul\code\squirrel\Squirrel.WindowsNG\src\Squirrel\UpdateManager.DownloadReleases.cs:line 38
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Squirrel.UpdateManager.<DownloadReleases>d__5.MoveNext() in c:\Users\paul\code\squirrel\Squirrel.WindowsNG\src\Squirrel\UpdateManager.cs:line 62
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at GoToWindow.ViewModels.SettingsViewModel.<Update>d__a.MoveNext() in d:\Dev\GoToWindow\GoToWindow\ViewModels\SettingsViewModel.cs:line 162
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__4(Object state)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

Make logging always work

Most people using Squirrel won't know what a Splat is. Let's make sure that users always get a log, even if they don't know about Splat logging.

When no files are available in the Setup.exe output, an error should be thrown

I expect Setup.exe file to throw an error message, e.g. "Invalid installer: No executable found" or something similar when no files are copied in a release.

In my case, it was a developer error, but even then such an error could avoid puzzled developers and potentially users and get them back on track more quickly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.