Giter Club home page Giter Club logo

iceventswg's Introduction

Inter-canister Events Working Group

Mission Statement

This group works towards the development and adoption of ICRC standards related to building an events system on the IC. This repository is used to collaborate, document decisions, discuss changes, raise issues and provide feedback.

Info on working groups: https://github.com/dfinity/ICRC

Standard Topic Status
X Next Status Badge
X Next Status Badge

Links

Announcement Post

[OpenChat] (https://oc.app/group/wgoc3-uiaaa-aaaar-bbbqa-cai/?ref=yenup-paaaa-aaaaf-aboha-cai)

Token Registry - Contribute and earn

Process

Status Description
Idea Just an idea
Issue Propose a topic as an issue
Draft Standard Write a draft of the final standard
Reference Implementation Build a reference implementation applying the standard in a practical scenario
Approved Spec Agree on solution design in the working group, which should represent the industry (sign off from X people in the group)
Community Approval Socialize spec (sign off from Y people in the community, including)
Standard ICRC Standard

Contributing

Everyone is welcome to join the public meetings of the working group.

  • If you want to discuss a specific topic, please create and issue or pull-request. We will go over all the newly created issues and PRs in the next meeting.
  • Add your file under /Meetings/YYYYMMDD/.

Tools:

Roles and Membership

Membership generally only takes a request to be added to the list along with your suggested roles. (Pull requests accepted.) But please also provide Austin with your plug principal.

Official Roles

  • Thought Leader: Review issues, and provide proactive responses and insight.
  • Voting Member: Vote on "Vote Required" GitHub issues.
  • Secretary: Responsible for recording meetings, producing notes, and providing attendance.
  • Treasurer: Responsible for minting tokens and keeping the ledger.
  • Developer Advocate: Acts as a liaison between the developers and the wider community. They gather feedback, promote the adoption of the system, and help in documenting and demonstrating the system’s capabilities.
  • Community Manager: Engages with users and potential contributors on platforms like forums, social media, and during public events. They build and maintain relationships within the community and gather user feedback for improvements.
  • Documentation Specialist: Creates and maintains clear and thorough documentation WG. Responsible for compiling and versioning Drafts.

Official Member List(You've given Austin a Principal):

  • Austin Fatheree Roles:

    • Thought Leader
    • Voting Member
    • Secretary (But would love a volunteer)
  • Ilia Agafonov

    Roles:

    • Thought Leader
    • Voting Member
  • Ethan Celletti

    Roles:

    • Thought Leader
    • Voting Member
  • Byron Becker

    Roles:

    • Voting Member
  • Lachlan Witham

    Roles

    • Thought Leader
    • Voting Member
  • Zhenya Usenko

    Roles:

    • Voting Member
  • Matthew Harmon

    Roles:

    • Voting Member

Meeting Recordings

iceventswg's People

Contributors

skilesare avatar icdevs avatar ava-vs avatar gekctek avatar

Stargazers

 avatar Sam Dr avatar  avatar

Watchers

Lachlan Witham avatar  avatar  avatar  avatar Jupes avatar  avatar  avatar

Forkers

samdrissi

iceventswg's Issues

Vote Required: Adopt Message ID

General Agreement: #4

Update the MessageNotification to include the Filter used in the message.

Switch to Principal instead of account.

type MessageNotification{
    id: nat
    timestamp: nat
    namespace: text;
    data: ICRC16;
    source: Principal;
    filter: ?text;
};

Include the following Text for the MessageNotification

*In eventing systems where atomicity of ordering is necessary across a range of event types, the system SHOULD separate concerns using data elements. Commonly filtered data items SHOULD appear as close to the Root as possible to reduce filter processing load.

Vote Required: Officially adopt role and member list

Official Roles

  • Thought Leader: Review issues, and provide proactive responses and insight.
  • Voting Member: Vote on "Vote Required" GitHub issues.
  • Secretary: Responsible for recording meetings, producing notes, and providing attendance.
  • Treasurer: Responsible for minting tokens and keeping the ledger.
  • Developer Advocate: Acts as a liaison between the developers and the wider community. They gather feedback, promote the adoption of the system, and help in documenting and demonstrating the system’s capabilities.
  • Community Manager: Engages with users and potential contributors on platforms like forums, social media, and during public events. They build and maintain relationships within the community and gather user feedback for improvements.
  • Documentation Specialist: Creates and maintains clear and thorough documentation WG. Responsible for compiling and versioning Drafts.

Official Member List(You've given Austin a Principal):

  • Austin Fatheree
    Roles:

    • Thought Leader
    • Voting Member
    • Secretary (But would love a volunteer)
  • Ilia Agafonov

    Roles:

    • Thought Leader
    • Voting Member
  • Ethan Celletti

    Roles:

    • Thought Leader
    • Voting Member
  • Byron Becker

    Roles:

    • Voting Member
  • Lachlan Witham

    Roles

    • Thought Leader
    • Voting Member
  • Zhenya Usenko

    Roles:

    • Voting Member
  • Matthew Harmon

    Roles:

    • Voting Member

Vote Required: General Consensus on Including Wild Cards at the Standard Level

#24

General Consensus has been reached that we should include wild cards in subscriptions at a protocol standard level, but that implementations MAY ignore these due to technical limitations.

Subscription Info

Subscription Registration Namespaces

Implementations MAY support wildcards for subscriptions. For example, a subscription to *.icrc1.transfer might register a subscriber to any events that produce a standard icrc1.transfer event regardless of the canister that emitted it. The subscription canister must take technical limitations into account when making these subscriptions as the canister may overload itself. The wild-card language that is used is purposely left out of this standard and must be defined by the implementation of the events system.

Filtering records

A subscriber MAY provide a filter in textual representation to filter out certain records for the subscription. Implementations SHOULD continue to develop CandyPath that can filter through ICRC-16 values, but the implementation MAY use a text query language of their own choosing.

Skipping records

A subscriber MAY provide a skip parameter to ask the canister to skip broadcasting for either bandwidth or distribution reasons. The skip parameter is a tuple of the mod and optional offset (nat, opt nat). If the mod is set then the subscriber should only receive a message if the mod of the value provided is 0. This can be offset for partitioning by using the optional partition variable. By using this pattern a subscriber set can ensure that all messages make it to a set of subscribers with a distributed message set.

type Skip = record {nat; opt nat};

type SubscriptionRegistration {
  namespace: Text;
  config: [ICRC16Map];
  filter: ?Text; 
  skip: ?Skip;
  stopped: Bool;
};

Valid Publisher/Subscriber List

Static vs Dynamic.

Do we use a variant:

#Static: [Principal];
#Dynamic: : {Principal} //calls icrc72_get_authorized_publishers(eventname) on target canister

icrc72_register_publication return type

Should it return bools that the item was processed, something more detailed? Errors?

Should the return include the assigned list of broadcasters? Or should that be retrievable elsewhere or broadcast to the publisher via a listening endpoint?

Vote Required: Issue New Tokens May 1, 2024

<style type="text/css"></style>

  To Be Issued Earned Issued
Ethan 60000 180000 120000
Fatheree 390000 1410000 1020000
Ilia 660000 960000 300000
Byron 0 120000 120000
Lachlan 60000 180000 120000
Zhenya 0 120000 120000
Matt H 180000 180000 0

<style type="text/css"></style>

4/17   Meeting 0    
  Fatheree   0   60000
  Ethan   0   60000
  Ilia   0   60000
  Lachlan   0   60000
  Zhenya   0   60000
  Matt H   60000   60000
4/17     0    
  Fatheree Meeting Follow up - 1 hr 0   60000
4/18     0    
  Fatheree Prep and Presentation to scaling WG 2hr 0   120000
4/23     0    
  Fatheree Meeting Prep 0   60000
  Ilia Git Hub issues 0   60000
4/24     0    
  Fatheree Meeting attendance 60000   60000
  Aje Meeting attendance 60000   60000
  Ethan Meeting attendance 60000   60000
  Matt H Meeting attendance 60000   60000
  Ilia Meeting attendance 60000   60000
  Lachlan Meeting attendance 60000   60000
4/24     0    
  Fatheree Meeting Follow Up - 1.5 hrs 90000   90000
4/29     0    
  Fatheree Meeting Prep and Draft updates - 4hrs. 240000   240000
4/30     0    
  Ilia Client Work and Type work - 6 hours 600000   600000

Renaming and updates to configs for publication

May need to add a broadcasterErrorNotification to the Publisher life cycle.

Fix PublicationUpdateRequest:

Icrc72:publication:publishers:allowed:list:add : Array([#Blob(PrincipalAsBlob])
Icrc72:publication:publishers:allowed:list:remove : Array([#Blob(PrincipalAsBlob])
Icrc72:publication:publishers:disallowed:list:add : Array([#Blob(PrincipalAsBlob])
Icrc72:publication:publishers:disallowed:list:remove : Array([#Blob(PrincipalAsBlob])
Icrc72:publication:publishers:allowed:icrc75:remove : #Text(”remove”);
Icrc72:publication:publishers:allowed:icrc75:update : Array([#Blob(CanisterIDAsBlob), #Text("namespace")]);
Icrc72:publication:publishers:disallowed:icrc75:remove : #Text(”remove”);
Icrc72:publication:publishers:disallowed:icrc75:update : Array([#Blob(CanisterIDAsBlob), #Text("namespace")]);
Icrc72:publication:controllers:add : Array([#Blob(PrincipalAsBlob])
Icrc72:publication:controllers:remove : Array([#Blob(PrincipalAsBlob])

  • UpdatePublicationResult to PublicationUpdateResult

Need to add PublicationUpdateError and fix it on UpdatePublicationResult(see above)

-update RegisterPublicationResult to PublicationRegisterResult

Vote Required: Token Issuance May 8th, 2024

<style type="text/css"></style>

  To Be Issued Earned Issued
Ethan 60000 240000 180000
Fatheree 180000 1590000 1410000
Ilia 60000 780000 720000
Byron 60000 180000 120000
Lachlan 240000 420000 180000
Zhenya 0 120000 120000
Matt H 60000 240000 180000

<style type="text/css"></style>

4/30     0    
  Ilia Client Work and Type work - 6 hours 0   360000
  Lachlan Nat and Type Review - 3 hours 180000   180000
5/1 Meeting   0    
  Fatheree   60000   60000
  Lachlan   60000   60000
  Byron   60000   60000
  Ilia   60000   60000
  Matt H   60000   60000
  Ethan   60000   60000
5/8 Meeting prep - 2hours   0    
  Fatheree Meeting prep - 2hours 120000   120000

Adopt CBOR as a standard binary encoding format for message payloads

Proposal to adopt CBOR 1 as a standard binary encoding & encapsulation format for message payloads.
I know it is used already in a number of IC code libraries & standards already.

Pros would be
(a) wide language support including Rust, Motoko(?), JS, python for canisters and just about any other used for off-chain clients, also many developer tools support inspection;
(b) easy to encode JSON data into compact and canonical form for transport (so deterministic data structure removing any text formatting variances of same data content);
(c) 1-4 byte Semantic Tags used in front of encoded binary data structures which can be used to either completely embed schema information or as a very compact reference to an external schema.

It is possible that open extension to the CBOR standard semantic tags dictionary can be done for identified IC payload data schemas e.g. we could formally assign a 2-byte CBOR semantic tag for each ICRC-X defined data schemas.

Also there is an assigned 1-byte tag for “CBOR data” which can be used as a ‘magic number’ for the first byte of a message payload to distinguish it trivially from a text payload or other binary message format.

Two types of subscriber Approach

Concept

To solve the problem of calling untrusted canisters, we propose to add 2 types of events:

  • for untrusted canister - untrusted subscriber receives one-way message
  • for trusted canister - trusted subscriber receives two-way message.

First type : untrusted canister, ICRC-3 data, one-way call, simple event type (e.g. GenericEvent)
Second type : trusted canister, registry or other verification method, ICRC-16 data, two-way call, some supported_protocols = [web socket, ftp, etc], advanced event type.

The first event type: For unverified canisters

Any canister can become a subscriber if it implements icrcx_event_listener and subscribes to the event hub:

	icrcx_event_listener : (GenericEvent) -> ();
    public type GenericEvent = {
        filters : [EventFilter];
        publisher : Principal; // canister_id        
        start_at : Nat64;  // UNIX timestamp
        expire_at : ?Nat64;
        data : [(Text, Value)];
        details : ?Text;
    };

	public type EventFilter = {
        eventType : ?EventName;
        category : Text; // category of event like "ICRC7Canister" or "ExtCanister"
		filter : ?Blob; // publisher, label, or other information
    };
	
	public type EventName = {
          #NFTCanister;
	  #News
	  #OfficialAnnouncement
          #EthereumEvent;
          #Other;
	}	

Example 1: How to Send an Event to Subscribers.

Use Case: You have deployed a new NFT canister.

Wallets should implement the method
'icrcx_event_listener : (GeneralEvent) -> ();'
and call the EventHub method 'subscribe' with argument

       {
	 filters : [EventFilter] = [{ name = "ICRC7Canister"; value=""}])'.
	}		

Your canister calls EventHub's emitEvent method with arguments:

      {
	  filters : [EventFilter] = [{ eventType = ?"NFTCanister"; category = "ICRC7Canister"; filter=null}];
          publisher : Principal = <your_nft_canister_id>; 
          start_at : Nat64 = <current_date>;
          expire_at : ?Nat64 = null;
          data : [(Text, Value)] = [];
          details : ?Text = null;
      }

EventHub will send information about a new NFT canister to all subscribers (wallets):

      let canister : GeneralEventActor= actor(event.publisher);
      canister.icrcx_event_listener(event);

Result: Wallets can handle your NFTs.

Vote Required: Token Issuance

<style type="text/css"></style>

  To Be Issued Earned Issued
Ethan 60000 300000 240000
Fatheree 570000 2160000 1590000
Ilia 60000 840000 780000
Byron 60000 240000 180000
Lachlan 0 420000 420000
Zhenya 60000 180000 120000
Matt H 120000 360000 240000

<style type="text/css"></style>

5/8 Meeting prep - 2hours   0    
  Fatheree Meeting prep - 2hours 0   120000
  Fatheree Meeting 60000   60000
  Ethan Meeting 60000   60000
  Byron Meeting 60000   60000
  Ilia Meeting 60000   60000
  Matt H Meeting 60000   60000
  Zhenya Meeting 60000   60000
  Fatheree ICRC-75 - 5 hours 300000   300000
5/14     0    
  Fatheree Meeting Prep 1.5 hours 90000   90000
5/15     0    
  Fatheree Meeting 60000   60000
  Matt H Meeting 60000   60000
5/20     0    
  Fatheree Meeting Prep 1hr 60000   60000

TransactionIds as returns

-Returning from register publication/register subscription -> Do we need a Nat to return the record id if we are recording transactions? This can be nullable for items that don't have transaction log?

type RegisterPublicationResult = variant {
  Ok: nat;
  Err: RegisterPublicationError;
};

vs

type RegisterPublicationResult = variant {
  Ok: {
   publicationId: nat;
   transactionId: opt nat;
  Err: RegisterPublicationError;
};

ICRC for Allow Lists

Should we prioritize specifying an ICRC standard for Allow lists that is generic enough for the IC, but accommodates what we might need to do as well?

icrcX_is_authorized(vec record {
namespace: Text;
principal: principal;
}) -> query vec[Bool];

icrcX_get_authorized({
namespace: Text;
prev: ?principal;
take: ?nat;
}) -> query vec[Principal];

icrcX_{adminfunctions}

Workflow for publishers vs publications - subscribers vs subscription - controllers

We currently do not have a register_publisher/registers_subscriber method? Do we assume that they are using register_publication? What if they don't have all of the configs? Is that ok as long as they are on the approved publisher/subscriber list?

I've added controllers as a concept to publications due to the fact that a service may register the publication for its publishers and want to control the namespace.

Current implementation:

  • By default the first publication declarer will be the controller.
  • Add Config for headers? icrc72:publication:controllers

Vote Required: Issue tokens 4/24/20224

<style type="text/css"></style>

  To Be Issued
Ethan 60000
Fatheree 300000
Ilia 60000
Byron 0
Lachlan 120000
Zhenya 120000

<style type="text/css"></style>

3/28/2024   Meeting Owed
  Ilia   0
  Fatheree   0
4/3/2024   Meeting 0
  Ilia   0
  Fatheree   0
  Sam   0
  Matt H   0
  Joseph   0
  Ebin   0
  Byron   0
  Zhenya   60000
  Dclan   0
  Nnadozi   0
  Unicorn   0
4/10   Pre Meeting work, Git setup, Draft, Agenda - 3 hours 0
  Fatheree   0
4/10     0
  Ilia   0
  Fatheree   0
  Ethan   0
  Byron   0
  Lachlan   60000
  JOrge   0
  Gilles   0
  Sam   0
4/11   Post meeting, notes, Open Chat, Github work 0
  Fatheree   0
4/14   Issue 2 and 3 Thoughts 1.5 hours 0
  Fatheree   0
4/17   Meeting Prep 0
  Fatheree   0
4/17   Meeting 0
  Fatheree   60000
  Ethan   60000
  Ilia   60000
  Matt   60000
  Lachlan   60000
  Zhenya   60000
4/17   Meeting Follow up - 1 hr 0
  Fatheree   60000
4/18   Prep and Presentation to scaling WG 2hr 0
  Fatheree   120000
4/23     0
  Fatheree Meeting Prep 60000

DAO proposal

I propose the following text of the proposal to create a DAO based on the ICRC-72 standard:

It is proposed to create a DAO that will manage a network of event broadcasters that implement the ICRC-72 Minimal Event-Driven Pub-Sub Standard. This DAO will perform the following functions:

  1. Launch and maintain one or more reference event broadcasters developed by the ICRC-72 Standardization Working Group team. These broadcasters will serve as the reference implementation of the standard.

  2. Maintain allow-lists of trusted event broadcasters. The DAO will vet broadcasters who wish to be whitelisted for compliance with ICRC-72 and security requirements.

  3. Provide information to customers (subscribers) about verified whitelisted broadcasters. This will help subscribers select reliable event sources.

  4. Coordinate the development of an ICRC-72-based broadcaster ecosystem, promote best practices, and assist developers in implementing the standard.

  5. Engage with the community to gather feedback on the broadcaster network and improve the ICRC-72 standard.

Vote Required: Issue 3 Resolution - EventId as Nat

Please Vote with a thumbs up emoji.

#3

Data Types

Event Identifiers

  1. Event identifiers MUST be represented as natural numbers with infinite precision. These numbers MAY be blob representations of more complex numbering schemes, converted to natural numbers. If an identifier is encoded, it MUST be encoded using Crockford's Base32, as specified at Crockford's Base32.

  2. Events MAY specify a prev_id to indicate the immediately preceding message identifier known by the broadcasting system. Event systems SHOULD provide null in scenarios where event ordering is not critical or where ordering depends on details internal to the identifier. Event systems MAY interpret the prev_id based on implementation specifics, such that:

    • In Single Publisher, Single Broadcaster systems, a consistent chain of messages SHOULD be maintained with no messages being dropped.

    • In Single Publisher, Multi-Broadcaster systems, a consistent chain of messaging SHOULD be maintained according to nonce partitioning, with no messages being dropped.

    • In Multi Publisher, Multi-Broadcaster systems, consistent chains SHOULD be maintained across publisher-based partitions. Each partition SHOULD either remain consistent or all messages MAY be ordered, provided there is an event-specific epoch close-out schema.

Todo: Draft ICRC-77 event replay extention

ICRC-77 Event Message Replay Interface


type MessageRequest {
  namespace: Text;
  range: (nat, ?nat);
  filter: ?Text;
  skip: ?Text;
};

type MessageFulfillmentId = nat;

icrc77_request_messages(vec MessageRequest) ->  vec[MessageFulfillmentId];
icrc77_cancel_messages_request(vec MessageFulfillmentId) ->  vec[MessageFulfillmentId];

Vote Required: Issue 2 Resolution - Two Subscriber Event Handlers

Resolve: #2

We have general consensus.

  icrcx_event_listener : (event: Event) -> async (); //untrusted
  icrcx_event_listener_trusted : (event: Event) -> async (opt Value);  //#Map for maps, #Nat for ID.

Presupposition: The trusted return type should only include response metadata and typically not have rich, stateful data.(emit your own event if you want to talk back to a publisher).

Note: Value may be ICRC3 Value or ICRC16 Depending on finalization of #13

Vote Required: Token Issuance

<style type="text/css"></style>

  To Be Issued Earned Issued
Ethan 0 300000 300000
Fatheree 780000 2940000 2160000
Ilia 120000 960000 840000
Byron 0 240000 240000
Lachlan 120000 540000 420000
Zhenya 0 180000 180000
Matt H 120000 480000 360000

<style type="text/css"></style>

5/22     0    
  Fatheree Meeting 60000   60000
  Matt H Meeting 60000   60000
  Lachlan Meeting 60000   60000
  Ilia Meeting 60000   60000
  Sam Meeting 60000   60000
  Fatheree ICRC-75 Updates - 1hr 60000   60000
5/23     0    
  Fatheree Draft Work - 4 hours 240000   240000
  Fatheree Draft Work - 3 hours 180000   180000
5/28     0    
  Fatheree Meeting Prep - 1.5 hour 90000   90000
  Fatheree RFP - Rust - 1.5 hour 90000   90000
5/29     0    
  Matt H Meeting 60000   60000
  Lachlan Meeting 60000   60000
  Ilia Meeting 60000   60000
  Fatheree Meeting 60000   60000

Message Identifier Discussion

The message identifier should be flexible enough so that for simple systems it can just be an increasing nonce, but for more complex systems we want deterministic ordering and the ability to know you missed a message.

How do we accomplish this?

Vector Clocks?
Lamport Timestamps?
Including previous complex nonce in each message?

{timestamp : Nat64} | {PublisherID: Nat64} | {(increasing nonce * broadcaster count)} //for partitioning

Publication Mode

Do we include some way to do this in the registration or leave it to the implementation?

Examples
FIFO, Subscription, ranked, captive

If we don't have some extensibility here then more complex methods will need a second call increasing latency.

Vote Required: Token Issuance 20240417

Please reply with a Thumbs up emoji to accept Token issuance:

Ethan 60000
Fatheree 720000
Ilia 240000
Byron 120000

3/28/2024   Meeting Earned
  Ilia   60000
  Fatheree   60000
4/3/2024   Meeting  
  Ilia   60000
  Fatheree   60000
  Sam    
  Matt H    
  Joseph    
  Ebin    
  Byron   60000
  Zhenya    
  Dclan    
  Nnadozi    
  Unicorn    
4/10   Pre Meeting work, Git setup, Draft, Agenda - 3 hours  
  Fatheree   360000
4/10      
  Ilia   60000
  Fatheree   60000
  Ethan   60000
  Byron   60000
  Lachlan    
  JOrge    
  Gilles    
  Sam    
4/11   Post meeting, notes, Open Chat, Github work  
  Fatheree   60000
4/14   Issue 2 and 3 Thoughts 1.5 hours 90000
  Fatheree   90000
4/14 Issue, PR, Review 1 hour 60000
Ilia 60000
4/17   Meeting Prep  
  Fatheree   30000

Vote Required: Adopt Generic Publication config variable

Resolve:
#5
#6

Use the following config type for the Publication and Subscription Registration

type Map = vec record { text; Value };;

type PublicationRegistration {
  namespace: Text;
  config : Map; //provide an empty map for null.
};

type SubscriptionRegistration {
  namespace: Text;
  filter: ?Text; //candypath
  skip: ?nat;
  stopped: Bool;
  config: Map;
};

Adopt the suggested standards :

[
     ("icrc72:publishers:allowed:list", Array([#Blob(PrincipalAsBlob]));
     ("icrc72:publishers:disallowed:list", Array([#Blob(PrincipalAsBlob]));
     // or
    ("icrc72:publishers:allowed:icrc75", Array([#Blob(CanisterIDAsBlob, #Text("namespace")]));
    //-----------
    ("icrc72:subscribers:allowed:list", Array([#Blob(PrincipalAsBlob]));
    ("icrc72:subscribers:disallowed:list", Array([#Blob(PrincipalAsBlob]));
     // or
    ("icrc72:subscribers:allowed:icrc75", Array([#Blob(CanisterIDAsBlob, 
];

We will not address Publication modes at this time and will allow those to grow as extensions to our base standard.

Financial Value

Should we provide for carrying financial value as a part of the spec? Or as an extension?

  • Publish with Cycles
  • TransferFrom

Rust ICRC-16 Library

We need to procure a rust dev to do this. We can offer WG tokens :). Maybe do a dfinity public grant?

Message Source

Principal vs Account

Allows a publisher to provide annotated source information in the subaccount. May be more complex.

Alternative: Put subaccount in data and leave it to the implementation.

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.